3

在我对Clojure For Comprehension 示例的回答中,我有一个处理自己的输出的函数:

(defn stream [seed]
  (defn helper [slow]
    (concat (map #(str (first slow) %) seed) (lazy-seq (helper (rest slow)))))
  (declare delayed)
  (let [slow (cons "" (lazy-seq delayed))]
    (def delayed (helper slow))
    delayed))

(take 25 (stream ["a" "b" "c"]))
("a" "b" "c" "aa" "ab" "ac" "ba" "bb" "bc" "ca" "cb" "cc" "aaa" "aab" "aac" 
"aba" "abb" "abc" "aca" "acb" "acc" "baa" "bab" "bac" "bba")

它通过创建一个前向引用 ( delayed) 来工作,该引用用作惰性序列 ( slow) 中的第二个条目。该序列被传递给惰性函数,然后该函数的输出(惰性序列的第一部分,不需要评估delayed)然后用于设置 的值delayed

这样我就“打结”了。但这在 Haskell 中做得更优雅(例如“打结”的解释</a>)。鉴于 Clojure 有delayand force,我想知道是否有更好的方法来完成上述操作?

delayed那么问题是:在上面的代码中是否可以以某种方式避免(丑陋的,显式的)突变(of )?显然(?)你仍然需要突变,但它可以被“惰性”结构隐藏吗?

[昨晚我还在试图理解如何做到这一点时,遇到了一个类似标题的问题;在上面的代码运行之前没有人回复,所以我删除了它,但我对这种方法并不满意,所以我再试一次。]

另请参阅:Clojure 循环数据结构是否必须涉及 ref 之类的构造?(有点令人沮丧的是人们在重复问题)。

4

1 回答 1

2

我不确定我能否回答一般情况的问题,但这个功能似乎可以解决特殊情况。

(defn stream
  [seed]
  (let [step (fn [prev] (for [p prev s seed] (str p s)))]
    (for [x (iterate step seed) y x] y)))

虽然我遇到了一个大的内存不足异常(dorun (take ...))。所以这个功能可能有问题。

于 2012-07-19T20:47:36.083 回答