编辑:我在写这篇文章的过程中发现了我自己问题的部分答案,但我认为它可以很容易地改进,所以无论如何我都会发布它。也许那里有更好的解决方案?
我正在寻找一种简单的方法来以一种let
形式定义递归函数,而无需借助letfn
. 这可能是一个不合理的要求,但我正在寻找这种技术的原因是因为我混合了数据和递归函数,这些函数在某种程度上需要大量的嵌套let
和letfn
语句。
我想编写生成这样的惰性序列的递归函数(以斐波那契序列为例):
(let [fibs (lazy-cat [0 1] (map + fibs (rest fibs)))]
(take 10 fibs))
但是在clojure中似乎fibs
不能在绑定期间使用它自己的符号。解决它的明显方法是使用letfn
(letfn [(fibo [] (lazy-cat [0 1] (map + (fibo) (rest (fibo)))))]
(take 10 (fibo)))
但是正如我之前所说,这会导致很多麻烦的嵌套和交替let
and letfn
.
为了在不letfn
使用和使用 just的情况下做到这一点let
,我首先编写了一些使用我认为是 U-combinator 的东西(今天刚刚听说过这个概念):
(let [fibs (fn [fi] (lazy-cat [0 1] (map + (fi fi) (rest (fi fi)))))]
(take 10 (fibs fibs)))
但是如何摆脱冗余(fi fi)
呢?
正是在这一点上,经过一个小时的挣扎并逐渐向组合子 Q 添加位,我找到了自己问题的答案。
(let [Q (fn [r] ((fn [f] (f f)) (fn [y] (r (fn [] (y y))))))
fibs (Q (fn [fi] (lazy-cat [0 1] (map + (fi) (rest (fi))))))]
(take 10 fibs))
Q
我用来定义递归序列的这个组合器叫什么?它看起来像没有参数的 Y 组合器x
。是一样的吗?
(defn Y [r]
((fn [f] (f f))
(fn [y] (r (fn [x] ((y y) x))))))
clojure.core 或 clojure.contrib 中是否有另一个函数提供 Y 或 Q 的功能?我无法想象我刚才所做的是惯用的......