我有一些代码当前给我一个错误,因为 recur 只能位于尾部位置。这是函数:
(defmethod transposer
Long [scale degree]
(loop [new-scale scale count degree]
(cond
(zero? count) new-scale
(< count 0) (recur (step (reverse new-scale)) (inc count)))
:else (recur (step new-scale) (dec count))))
我认为解决这个问题的一种方法是条件绑定(bind),如果我可以说: 当count小于零时,将count-operator设置为“inc”,否则设置为“dec”,然后在最后重复。
那么这将解决我的问题。但我不确定如何在 clojure 中执行此操作,或者如果可能的话,when-let 和 if-let 似乎不会执行此操作。将我的代码修复为仅使用一次重复的最佳方法是什么?
编辑:我在这里学到了一些东西:
1) 如果没有循环语句,“recur”将递归回到 defn。在我读的书中,所有recur的例子都使用loop/recur,所以我认为有一个循环是有必要的。事实并非如此,我的循环语句是多余的。
2) 括号错误给了我一个令人困惑的错误,令我感到奇怪的是,两个 cond 语句都不会被视为位于尾部,因为它们是互斥的。我应该更加注意我的 paren 完成检查器。
3) 如果我确实想要进行条件绑定(bind),我可以使用标准的“let”语句并仅在其中包含条件逻辑。由于我有 Java 背景,我有时会忘记 clojure 在这方面所提供的灵 active 。
最佳答案
(defn foo [scale degree]
(loop [new-scale scale count degree]
(cond
(zero? count) new-scale
(< count 0) (recur (step (reverse new-scale)) (inc count))
:else (recur (step new-scale) (dec count)))))
我认为更接近你想要的(它不会给出尾部错误;我只是使用 defn 来测试独立)。
多次recur
没有问题 - 尾递归并不意味着它必须在文本的最后一行,只是在返回时不再进行计算。
主要问题是括号困惑(count
之后太多)。我建议使用一个自动缩进的编辑器(并过度使用自动缩进)。这会立即显示parens问题(我在intellij idea中使用la clojure插件,但我确信其他人也有类似的功能)。
更新:为什么需要循环
?
(defn foo [scale degree]
(cond
(zero? degree) scale
(< degree 0) (recur (step (reverse scale)) (inc degree))
:else (recur (step scale) (dec degree))))
关于clojure:在 cond 中使用绑定(bind)仅将 recur 放置在尾部位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10508591/