我的 Clojure 循环中的尾部位置在哪里?

Where is the tail position in my Clojure loop?

Clojure 说我不能从非尾位置调用 recur

这不是尾位吗?

那么是什么我循环中的尾部位置?

(loop [i 20]
    (for [x (range 1 21)]
      (if (zero? (rem i x))
        i
        (recur (+ i 1)))))

for 并不像您认为的那样;这不是命令式循环。它是一个列表理解或序列生成器。因此,在其末尾没有 return 或迭代调用,因此您不能在此处放置 recur

看起来您可能根本不需要此表达式中的 looprecurfor 是构建序列所需的全部内容,但我不清楚您希望构建什么序列。

进一步 ,任何 recur 指的是(最近的)包围 loopfn(可以装扮成 letfn 或一个 defn)。您的代码段中没有这样的东西。所以 recur 没有什么可以处于尾部位置的。

但是只需将 for 替换为 loop,您就会得到

(loop [i 20]
  (loop [x 1]
    (if (zero? (rem i x))
      i
      (recur (+ i 1)))))

... 计算结果为 20,毫无疑问您的意图是什么。

然而,外部 loop 永远不会重复出现,所以很可能是 let:

(let [i 20]
  (loop [x 1]
    (if (zero? (rem i x))
      i
      (recur (+ i 1)))))

recur 处于尾部位置,因为在通过 loop 形式的控制路径中没有什么可做的:recur 形式 is返回值。 if 的双臂都有自己的尾部位置。

还有一些变相的if有自己的尾部位置:orand就是这样。