延迟调用无限序列 clojure 的函数

问题描述 投票:0回答:1

我对 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 的操作,而不是移位并添加所有元素。优雅但对于原始斐波那契定义来说并不那么明显。

有没有办法避免使用地图。

recursion clojure fibonacci
1个回答
0
投票

给猫剥皮的方法有很多,但使用

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 迭代器之间的紧密联系。

© www.soinside.com 2019 - 2024. All rights reserved.