这有效:
(defn tri*
([] (tri* 0 1))
([sum n]
(let [new-sum (+ sum n)]
(cons new-sum (lazy-seq (tri* new-sum (+ n 1)))))))
Run Code Online (Sandbox Code Playgroud)
但当我使用recur它时,我得到一个CompilerException:
不匹配的参数计数重复,预期0参数,得到:2
(defn tri*
([] (tri* 0 1))
([sum n]
(let [new-sum (+ sum n)]
(cons new-sum (lazy-seq (recur new-sum (+ n 1)))))))
Run Code Online (Sandbox Code Playgroud)
lazy-seq是一个宏,它扩展为涉及零arg thunk的代码,可以在实现序列时调用.您可以看到recur表单被捕获为此thunk的主体
(macroexpand '(lazy-seq (recur new-sum (+ n 1))))
Run Code Online (Sandbox Code Playgroud)
要得到
(new clojure.lang.LazySeq (fn* [] (recur new-sum (+ n 1))))
Run Code Online (Sandbox Code Playgroud)
这表明目标recur是thunk,而不是tri*.
考虑所有这一切的另一种方式是,原始调用tri*早已完成(并且返回Cons包含LazySeqrest对象的对象)recur将被"评估".
您的第一个版本tri*很好,因为递归调用tri*不会增加堆栈,而只是创建一组新的Cons/ LazySeqobjects.