Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Clojure have "unfold"?

(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

like image 861
Dan Burton Avatar asked Dec 16 '15 19:12

Dan Burton


1 Answers

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.

like image 153
Timothy Pratley Avatar answered Oct 21 '22 12:10

Timothy Pratley