5
(defn unfold [step seed]
  (if-let [[val new-seed] (step seed)]
    (cons val (lazy-seq (unfold step new-seed)))
    nil))

Example usage:

(defn fib-step [[x y]] [x [y (+ x y)]])
(take 10 (unfold fib-step [0 1])) ;=> (0 1 1 2 3 5 8 13 21 34)

(defn decreasing [x] (if (neg? x) nil [x (dec x)]))
(unfold decreasing 5) ;=> (5 4 3 2 1 0)

Does this or something like it exist in clojure standard (or commonly used) libs? If not, is there a reason why? The closest I've found is this blog post:

http://www.matlux.net/blog/2014/05/04/anamorphic-adventure-in-clojure

Dan Burton
  • 51,332
  • 25
  • 109
  • 190

1 Answers1

5

No, unfold is not implemented in Clojure. It is provided by amalloys flatland.useful library, which has wide usage according to CrossClj. Seeing as the blog post you linked provides quite a deep exploration of the subject, I suspect there is more to your question than a direct answer can satisfy... Do you have some scenario in mind where iterate is inadequate? Or disappointed that iterate is not quite unfold in name or behavior?

(defn fib-step [[a b]] [b (+ a b)])
(take 10 (map first (iterate fib-step [0 1])))

(take-while (complement neg?) (iterate dec 5))

I prefer to use iterate for these examples because iterate is part of core already. I can see people preferring unfold if that is more familiar to them.

There are many libraries that provide "things that should have been in core" such as https://weavejester.github.io/medley/medley.core.html. A quick search on https://crossclj.info/ reveals https://github.com/amalloy/useful contains flatland.useful.seq/unfold, which though I have not used looks to be a great implementation by a Clojure core contributor and comes with some other cool stuff to boot.

Timothy Pratley
  • 10,106
  • 3
  • 29
  • 55
  • I've forgotten what motivated me to ask the question, but I just wanted to get a better idea of how to write idiomatic clojure for such tasks. I think your answer does a good job of providing the sort of information I was looking for. – Dan Burton Dec 30 '15 at 23:38