4

I am playing a bit with atoms in clojure. I have an atom pointing at a lazy-seq. In another bit of code I want to update the value of the atom to the result of doing next on the sequence, but given that both swap! and reset! return the updated value execution never ends. I figured out that I could always wrap the call to swap!, reset! in a do statement and then return nil, but I am wondering how idiomatic this is or whether there is an alternative solution to do it.

Doesn't terminate:

(def x (atom (range)))
(swap! x next)

Terminates

(def x (atom (range)))
(do (swap! x next) nil)
(first @x) ;1
(do (swap! x next) nil)
(first @x) ;2
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
emanjavacas
  • 109
  • 2
  • 7

2 Answers2

8

The problem here isn't so much with Clojure, but with the repl you are using. The call to swap! is working just fine, it's that the repl is attempting to print out the result and it can't since the sequence never ends. You can set the number of items printed by Clojure's built-in repl via (set! *print-length* 10). But this won't always work if you have other REPL middleware that performs different print logic.

On the topic of "what is the idiomatic way of doing this", I'd give you two options:

  1. Wrap your call to swap! in a function that returns something different.
  2. Or, in the use case above, put an integer in the atom then use (swap! x inc) to get the next integer.
Thumbnail
  • 13,293
  • 2
  • 29
  • 37
Timothy Baldridge
  • 10,455
  • 1
  • 44
  • 80
  • Thanks! that gives a solution to my problem. I guess wrapping the call in a do statement should then be considered idiomatic as per your first option – emanjavacas Apr 28 '15 at 08:19
1

Well, you could just combine the swap! and first:

(def x (atom (range)))
(first (swap! x next))
(first (swap! x next))

But I'm not sure why you'd want to wrap the infinite list and then only use the first value each time. Seems like this would be simpler and yield the same results:

(def x (atom 0))
(swap! x inc)
(swap! x inc)
Alex Miller
  • 69,183
  • 25
  • 122
  • 167
  • thanks for your answer, actually this is a simplified version of my code. In reality I don't have just range but another kind of lazy-seq in which not always the next value is the previous value plus one. – emanjavacas Apr 27 '15 at 16:49