编辑:我在写这篇文章的过程中发现了我自己问题的部分答案,但我认为它很容易改进,所以无论如何我都会发布它.也许那里有更好的解决方案?
我正在寻找一种简单的方法来定义let表单中的递归函数而不诉诸letfn.这可能是一个不合理的请求,但我寻找这种技术的原因是因为我混合了数据和递归函数,这些函数在某种程度上相互依赖需要大量的嵌套let和letfn语句.
我想编写生成这样的惰性序列的递归函数(以Fibonacci序列为例):
(let [fibs (lazy-cat [0 1] (map + fibs (rest fibs)))]
(take 10 fibs))
Run Code Online (Sandbox Code Playgroud)
但似乎在clojure中,fibs在绑定期间不能使用它自己的符号.显而易见的是使用它letfn
(letfn [(fibo [] (lazy-cat [0 1] (map + (fibo) (rest (fibo)))))]
(take 10 (fibo)))
Run Code Online (Sandbox Code Playgroud)
但正如我刚才所说,这导致了很多繁琐的嵌套和交替的let和letfn.
为了在没有letfn和使用的情况下做到这一点let,我开始编写一些使用我认为的U-combinator的东西(刚刚听说过这个概念):
(let [fibs (fn [fi] (lazy-cat [0 1] (map + (fi fi) (rest (fi fi)))))]
(take 10 (fibs fibs)))
Run Code Online (Sandbox Code Playgroud)
但如何摆脱冗余(fi fi)呢?
正是在这一点上,经过一个小时的挣扎并逐渐向组合子Q添加位,我发现了自己问题的答案.
(let [Q (fn [r] …Run Code Online (Sandbox Code Playgroud) 对任何错误的术语表示歉意 - 我对计算机科学很陌生,我几乎只知道Clojure(但我想我会说我很清楚).
所以,我还没有对此做过大量的研究,但我有时发现在编写Clojure代码时能够从该数据结构中引用一些"我所处的任何数据结构的中间版本" (很像a let).快速举例:
=> (self-ish {:a 10
:b (inc (this :a))
:c (count (vals this))})
=> {:a 10, :b 11, :c 3}
=> (self-ish ["a" "b" (reduce str this)])
=> ["a" "b" "ab"]
//Works in any nested bits too
=> (self-ish [1 2 3 [4 5 (first this)] 6 [7 [8 (cons (second this) (nth this 3))]]])
=> [1 2 3 [4 5 1] 6 [7 [8 (2 4 5 1)]]]
Run Code Online (Sandbox Code Playgroud)
这个想法是结构逐渐建立起来,并且在任何阶段都有能力将当前的中间结构称为this.这是我当前实现的代码:
//Random straightforward …Run Code Online (Sandbox Code Playgroud)