clojure - 使用循环并使用惰性序列重复

时间:2015-01-11 07:06:22

标签: clojure lazy-evaluation

如果我从这样的函数返回一个lazy-seq:

(letfn [(permutations [s]
              (lazy-seq
               (if (seq (rest s))
                 (apply concat (for [x s]
                                 (map #(cons x %) (permutations (remove #{x} s)))))
                 [s])))])

如果我使用如下所示的循环重复,是否会急切地评估该列表?

(loop [perms (permutations chain)]
       (if (empty? perms)
         (prn "finised")
         (recur (rest perms))))

如果热切评估,我可以使用loop..recur来懒散地循环从permutations函数返回的内容吗?

1 个答案:

答案 0 :(得分:6)

您的循环重复代码会懒惰地评估该列表。

你可以自己尝试一下。每次通过添加permutations调用返回值时,让我们println打印一些内容。

(defn permutations [s]
  (lazy-seq
   (if (seq (rest s))
     (apply concat (for [x s]
                     (map #(cons x %) (permutations (remove #{x} s)))))
     (do
       (println "returning a value")
       [s]))))

使用loop时,我们也会使用(prn (first perms)循环播放值。

(loop [perms (permutations [1 2 3])]
  (if (empty? perms)
    (prn "finised")
    (do
      (prn (first perms))
      (recur (rest perms)))))

这是它打印的内容:

returning a value
(1 2 3)
returning a value
(1 3 2)
returning a value
(2 1 3)
returning a value
(2 3 1)
returning a value
(3 1 2)
returning a value
(3 2 1)
"finished"

如您所见,“返回一个值”和值行是交错的。可以使用doall强制评估惰性seq。如果你循环遍历(doall (permutations [1 2 3])),首先它会打印所有“返回值”行,然后只打印值。