我对 clojure 很陌生,想要制作显而易见的程序。
(def fib (conj fib (apply + (take-last 2 fib))))
不起作用,因为没有惰性评估,也没有开始的指示 [0 1]
(def fib ( (fn [array] (recur (conj array (apply + (take-last 2 array))))) [0 1]))
这里 recur
似乎没有被懒惰地评估。
与(Clojure 中的递归斐波那契函数)高度相关 然而,它们使用循环和计数或多元性。我想知道如果没有这个,这个问题是否可能存在。
(def fib (lazy-cat [0 1] (map + fib (rest fib))))
是一个非常好的解决方案,但以某种方式隐藏了 fx = fx-1 + fx-2 的操作,而不是移位并添加所有元素。优雅但对于原始斐波那契定义来说并不那么明显。
有没有办法避免使用地图。
给猫剥皮的方法有很多,但使用
lazy-seq
来实现斐波那契数列可以说是最漂亮的。但iterate
功能也不错。
以下是斐波那契数列的三种实现,它们都会产生越来越丑陋的惰性序列。
(defn fib
([] (fib 0 1))
([a b]
(lazy-seq
(cons a (fib b (+ a b))))))
(take 20 (fib))
;; => (0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181)
(defn fib2 []
(map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])))
(take 20 (fib2))
;; => (0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181)
(defn fib3 []
(iterator-seq
(let [state (atom [0 1])]
(reify java.util.Iterator
(hasNext [_] true)
(next [_] (ffirst (swap-vals!
state
(fn [[a b]]
[b (+ a b)]))))))))
(take 20 (fib3))
;; => (0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181)
但我不推荐最后一个创建 Java 迭代器并用
iterator-seq
包装它的方法。但我仍然将它包含在内,以展示 Clojure 惰性序列和 Java 迭代器之间的紧密联系。