今天我看到了一些关于“tying the knot”和循环数据结构的参考资料。我读了一些答案,这些解决方案似乎涉及使用一个引用指向列表头部。一个特定的 SO问题展示了一个Haskell示例,但我不太了解Haskell,不知道该示例是否使用了Haskell等效的引用。有没有一种方法可以使Clojure数据结构循环而不使用ref或类似的构造?谢谢。
我直接将Haskell的例子翻译成了Clojure:
user> (def alternates
(letfn [(x [] (lazy-seq (cons 0 (y))))
(y [] (lazy-seq (cons 1 (x))))]
(x)))
#'user/alternates
user> (take 7 alternates)
(0 1 0 1 0 1 0)
它按预期工作。然而,我更喜欢使用cycle
函数而不是使用letfn
相互递归的函数:
user> (take 7 (cycle [0 1]))
(0 1 0 1 0 1 0)
使用标准的Clojure不可变数据结构和标准的Clojure函数,无法创建循环引用。这是因为第二个创建的对象永远无法添加到先创建的(不可变)对象中。
但是,如果您愿意使用一些技巧,有多种方法可以创建循环数据结构:
然而,在Clojure中,通常最好避免使用循环数据结构。
我以前用过这个:
;; circular list operations
(defn rotate
([cl] (conj (into [](rest cl)) (first cl)))
([cl n] (nth (iterate rotate cl) (mod n (count cl)))))