clojure - 使用循环并通过惰性序列重复出现

clojure - using loop and recur with a lazy sequence

如果我从这样的函数返回惰性序列:

(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 函数返回的内容吗?

该列表由您的循环递归代码延迟计算。

你可以自己试试看。让我们通过添加 println 调用让 permutations 每次 returns 打印一些值。

(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"

如您所见,"returning a value" 和值线是交错的。惰性序列的评估可以用 doall 强制执行。如果您遍历 (doall (permutations [1 2 3])),首先它会打印所有 "returning a value" 行,然后才打印值。