5

今天我看到了一些关于打结和循环数据结构的参考资料。我一直在阅读一些答案,解决方案似乎涉及使用 ref 指向列表的头部。一个特定的SO 问题显示了一个 Haskell 示例,但我不太了解 Haskell,无法知道该示例是否使用了 Haskell 等效的 ref。

有没有办法在不使用 ref 或类似构造的情况下使 Clojure 数据结构循环?

谢谢。

4

3 回答 3

6

我直接将 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)
于 2012-07-19T21:06:57.750 回答
6

使用标准 Clojure 不可变数据结构和标准 Clojure 函数创建循环引用是不可能的。这是因为第二个创建的对象永远不能添加到第一个创建的(不可变的)对象中。

但是,如果您愿意使用一些技巧,可以通过多种方式创建循环数据结构:

  • 参考,原子等。
  • 可变的定义类型
  • Java 对象
  • 反射诡计
  • 惰性序列

然而,一般来说,在 Clojure 中最好避免使用循环数据结构。

于 2012-07-20T04:12:24.280 回答
3

我以前用过这个:

;; circular list operations
(defn rotate
   ([cl] (conj (into [](rest cl)) (first cl)))
   ([cl n] (nth (iterate rotate cl) (mod n (count cl)))))

输出是一个向量,但输入可以是任何序列。

于 2012-07-19T20:05:58.647 回答