很抱歉,如果这是重复的话。如果是这样,我找不到原件。我也很难在Clojure文档中找到答案。无论如何,我是Clojure的新手,似乎你可以用两种不同的方式使用ids_list = range(1000000)
ids_set = set(ids)
def f(x):
for i in x:
pass
%timeit f(ids_set)
#1 loops, best of 3: 214 ms per loop
%timeit f(ids_list)
#1 loops, best of 3: 176 ms per loop
并且基本上得到相同的结果。
示例1:
recur
示例2:
(defn my-function [num]
(if (> num 10)
num
(recur (+ num 1))))
据我所知,这两种形式似乎完全相同。我理解(defn my-function [num]
(loop [cnt num]
(if (> cnt 10)
cnt
(recur (+ cnt 1)))))
一般是好的原因是在正确的情况下,编译器可以将某种伪尾调用优化混合在一起,我非常喜欢并希望尽可能多地使用它。所以这是我的问题:
recur
在没有loop
的情况下使用recur
时有什么需要?loop
只是创建一个"递归范围"有点像let
如何创建迷你范围?loop
的情况下获得尾递归优势?答案 0 :(得分:4)
只是逐一回答你的问题:
loop
允许您接受并传递任意参数。如果没有loop
,您将受到限制,只能传递函数接受的内容。它会导致大量微小的辅助功能
是的,有点
它必须是尾调用,并且受编译器
答案 1 :(得分:2)
loop
。您可以始终替换它
拨打匿名fn
表单。 loop
充当let
,可以作为递归点使用
recur
。如果loop
没有捕获recur
,则可以将其替换为。{1}}
let
,反之亦然。recur
实现尾递归(并且只有尾部
递归),无论是递归到loop
还是fn
形式。为了说明(1),您可以替换示例2中的loop
表单
(loop [cnt num]
(if (> cnt 10)
cnt
(recur (+ cnt 1))))
...与
((fn [cnt] (if (> cnt 10) cnt (recur (+ cnt 1)))) num)
...正如您所见,它创建并调用匿名函数。
您甚至可以将loop
写为进行此转换的宏:
(defmacro loop [bindings & body]
(let [[names values] (apply map vector (partition 2 bindings))]
`((fn ~names ~@body) ~@values)))
(loop [i 10, ans 0]
(case i
0 ans
(recur (dec i) (+ ans i))))
; 55
这可能比正确的clojure.core/loop
慢。