7

在 clojure 中,这是有效的:

(loop [a 5]
  (if (= a 0)
    "done"
    (recur (dec a))))

然而,这不是:

(let [a 5]
  (if (= a 0)
    "done"
    (recur (dec a))))

所以我想知道:为什么循环和让分开,因为它们都(至少在概念上)引入了词法绑定?也就是说,为什么 loop 是循环目标,而 let 不是?

编辑:最初写的“循环目标”我注意到是不正确的。

4

1 回答 1

6

考虑以下示例:

(defn pascal-step [v n]
  (if (pos? n)
      (let [l (concat v [0])
            r (cons 0 v)]
        (recur (map + l r) (dec n)))
      v))

该函数n+m通过给定的第 条线计算帕斯卡三角形的m第 条线。

现在,想象一下,这let是一个recur目标。在这种情况下,我将无法使用运算符从绑定中递归调用pascal-step函数本身。letrecur

现在让我们让这个例子更复杂一点:

(defn pascal-line [n]
  (loop [v [1]
         i n]
    (if (pos? i)
        (let [l (concat v [0])
              r (cons 0 v)]
          (recur (map + l r) (dec i)))
        v)))

现在我们正在计算n帕斯卡三角形的第 条线。如您所见,我需要两者looplet这里。

这个例子很简单,所以你可能会建议直接let使用(concat v [0])and删除绑定(cons 0 v),但我只是向你展示这个概念。可能有一个更复杂的例子,其中letaloop是不可避免的。

于 2013-10-04T10:28:59.380 回答