【问题标题】:Clojure Loop can only recur from tail positionClojure Loop 只能从尾部位置重复
【发布时间】:2020-11-07 10:01:07
【问题描述】:

我想创建 500 个圈子,但只有在新圈子不与现有圈子发生冲突时才添加它们。

这是我的循环

  (let [total-circles 500
        circles (loop [n 0 {:keys [x y d] :as circle} (create-circle) circles ()]
                  (cond
                    (>= n total-circles) circles

                    (if (not (does-circle-have-a-collision circles circle))
                      (recur (inc n) (create-circle) (conj circles circle))
                      (recur n (create-circle) circles))

                    :else (recur (inc n) (create-circle) circles)))])

错误信息是

在 (sketch/dynamic.clj:82:21) 处重新编译时出现语法错误 (UnsupportedOperationException)。 只能从尾部位置重复

我的代码有什么问题?

【问题讨论】:

    标签: clojure


    【解决方案1】:

    cond 采用 pairs 中的子句,特别是 test/expr 对。这意味着cond 里面应该总是有偶数个表格,但你的表格没有。您的(if ...) 表单位于test 的位置,没有后续的expr。如果我们缩写事物来查看结构,它看起来是这样的:

    (cond
      ;; test    ;; expr
      (>= ...)   circles
      (if ...)   !!!missing!!!
      :else      (recur ...))
    

    解决此问题的一种方法是从您的if 中提取测试,但删除if,如下所示。 (注意:我在没有测试的情况下重新排列了您现有的逻辑,所以不确定这是否真的有效,但结构是正确的。我还将test/expr 对放在单独的行上,并缩进exprs 所以他们脱颖而出。)

    (cond
      ;; test
        ;; expr
      (>= n total-circles) 
        circles
      (does-circle-have-a-collision circles circle) 
        (recur n (create-circle) circles)
      :else 
        (recur (inc n) (create-circle) (conj circles circle)))
    

    在上面,从任何expr 子句调用recur 都可以。

    您正在跟踪您可能不需要的loop/recur 中的绑定。例如,您无需跟踪n,只需查看您圈子集合的count。假设你有一个函数

    (defn add-if-no-overlap [coll c] ...)
    

    如果它不与coll 中已有的任何圆圈重叠,则返回coll 并添加c,否则返回coll。然后你可以像这样生成你的 500 个不重叠的圆圈:

    (defn generate-circles [total]
      (loop [circles ()]
        (if (< (count circles) total)
          (recur (add-if-no-overlap circles (create-circle)))
          circles)))
    
    (generate-circles 500)
    

    【讨论】:

    • 感谢您的帮助。我对 Clojure 很陌生,有时我不知道出了什么问题。我的目标是创建不重叠的圆圈。所以需要在第一个示例中通过更改代码来更改我的逻辑。我必须将 does-circle-have-a-collision 更改为 does-circle-have-NOT-a-collision。
    • 我现在明白你所说的碰撞/重叠是什么意思了。我将编辑我的答案以反映这一点。
    【解决方案2】:

    您的cond 结构不正确。结构应该是

    (cond if1 then1
          if2 then2
          if3 then3)
    

    但你有

    (cond if1 then1
          ???mystery stuff???
          if2 then2)
    

    按照cond 期望的方式重组你的神秘物品。

    【讨论】:

    • 是的,这是我的问题。如何重组?
    猜你喜欢
    • 2012-06-07
    • 1970-01-01
    • 2016-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多