今天我看到了一些关于打结和循环数据结构的参考资料。我一直在阅读一些答案,解决方案似乎涉及使用 ref 指向列表的头部。一个特定的SO 问题显示了一个 Haskell 示例,但我不太了解 Haskell,无法知道该示例是否使用了 Haskell 等效的 ref。
有没有办法在不使用 ref 或类似构造的情况下使 Clojure 数据结构循环?
谢谢。
今天我看到了一些关于打结和循环数据结构的参考资料。我一直在阅读一些答案,解决方案似乎涉及使用 ref 指向列表的头部。一个特定的SO 问题显示了一个 Haskell 示例,但我不太了解 Haskell,无法知道该示例是否使用了 Haskell 等效的 ref。
有没有办法在不使用 ref 或类似构造的情况下使 Clojure 数据结构循环?
谢谢。
我直接将 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)))))
输出是一个向量,但输入可以是任何序列。