Clojure 中惯用的惰性原子
idiomatic lazy atoms in clojure
我在 Clojure 中玩了一下原子。我有一个 atom
指向 lazy-seq
。在另一段代码中,我想将原子的值更新为对序列执行 next
的结果,但考虑到更新后的 swap!
和 reset!
return价值执行永无止境。
我发现我总是可以在 do 语句中包装对 swap!
、reset!
的调用,然后是 return nil
,但我想知道这是多么地道,或者是否有是另一种解决方案。
不终止:
(def x (atom (range)))
(swap! x next)
终止
(def x (atom (range)))
(do (swap! x next) nil)
(first @x) ;1
(do (swap! x next) nil)
(first @x) ;2
好吧,你可以结合交换!第一个:
(def x (atom (range)))
(first (swap! x next))
(first (swap! x next))
但我不确定您为什么要包装无限列表,然后每次只使用第一个值。看起来这样会更简单并产生相同的结果:
(def x (atom 0))
(swap! x inc)
(swap! x inc)
这里的问题不在于 Clojure,而在于您正在使用的 repl。对 swap!
的调用工作得很好,因为 repl 正试图打印出结果但它不能,因为序列永远不会结束。您可以通过 (set! *print-length* 10)
设置 Clojure 内置 repl 打印的项目数。但是,如果您有其他执行不同打印逻辑的 REPL 中间件,这并不总是有效。
关于"what is the idiomatic way of doing this"这个话题,我给你两个选择:
- 将对
swap!
的调用包装在一个 returns 函数中
不同。
- 或者,在上面的用例中,将一个整数放入原子中,然后使用
(swap! x
inc)
获取下一个整数。
我在 Clojure 中玩了一下原子。我有一个 atom
指向 lazy-seq
。在另一段代码中,我想将原子的值更新为对序列执行 next
的结果,但考虑到更新后的 swap!
和 reset!
return价值执行永无止境。
我发现我总是可以在 do 语句中包装对 swap!
、reset!
的调用,然后是 return nil
,但我想知道这是多么地道,或者是否有是另一种解决方案。
不终止:
(def x (atom (range)))
(swap! x next)
终止
(def x (atom (range)))
(do (swap! x next) nil)
(first @x) ;1
(do (swap! x next) nil)
(first @x) ;2
好吧,你可以结合交换!第一个:
(def x (atom (range)))
(first (swap! x next))
(first (swap! x next))
但我不确定您为什么要包装无限列表,然后每次只使用第一个值。看起来这样会更简单并产生相同的结果:
(def x (atom 0))
(swap! x inc)
(swap! x inc)
这里的问题不在于 Clojure,而在于您正在使用的 repl。对 swap!
的调用工作得很好,因为 repl 正试图打印出结果但它不能,因为序列永远不会结束。您可以通过 (set! *print-length* 10)
设置 Clojure 内置 repl 打印的项目数。但是,如果您有其他执行不同打印逻辑的 REPL 中间件,这并不总是有效。
关于"what is the idiomatic way of doing this"这个话题,我给你两个选择:
- 将对
swap!
的调用包装在一个 returns 函数中 不同。 - 或者,在上面的用例中,将一个整数放入原子中,然后使用
(swap! x inc)
获取下一个整数。