在 clojure 中,这是有效的:
(loop [a 5]
(if (= a 0)
"done"
(recur (dec a))))
然而,这不是:
(let [a 5]
(if (= a 0)
"done"
(recur (dec a))))
所以我想知道:为什么循环和让分开,因为它们都(至少在概念上)引入了词法绑定?也就是说,为什么 loop 是循环目标,而 let 不是?
编辑:最初写的“循环目标”我注意到是不正确的。
在 clojure 中,这是有效的:
(loop [a 5]
(if (= a 0)
"done"
(recur (dec a))))
然而,这不是:
(let [a 5]
(if (= a 0)
"done"
(recur (dec a))))
所以我想知道:为什么循环和让分开,因为它们都(至少在概念上)引入了词法绑定?也就是说,为什么 loop 是循环目标,而 let 不是?
编辑:最初写的“循环目标”我注意到是不正确的。
考虑以下示例:
(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
函数本身。let
recur
现在让我们让这个例子更复杂一点:
(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
帕斯卡三角形的第 条线。如您所见,我需要两者loop
和let
这里。
这个例子很简单,所以你可能会建议直接let
使用(concat v [0])
and删除绑定(cons 0 v)
,但我只是向你展示这个概念。可能有一个更复杂的例子,其中let
aloop
是不可避免的。