У Clojure есть "разворачиваться"?

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

Пример использования:

(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)

Существует ли это или что-то подобное в стандартных (или часто используемых) библиотеках clojure? Если нет, то есть ли причина? Самый близкий, который я нашел, является этим сообщением в блоге:

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

1 ответ

Решение

Нет, unfold не реализовано в Clojure. Он предоставляется библиотекой amalloys flatland.useful, широко используемой в соответствии с CrossClj. Поскольку пост в блоге, на который вы ссылаетесь, достаточно глубоко изучает эту тему, я подозреваю, что ваш вопрос может дать гораздо больше, чем прямой ответ... У вас есть какой-то сценарий, в котором iterate неадекватно? Или разочарован тем, что iterate не совсем unfold по названию или поведению?

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

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

Я предпочитаю использовать iterate для этих примеров, потому что iterate уже является частью ядра. Я вижу людей, предпочитающих unfold если это более знакомо им.

Есть много библиотек, которые предоставляют "вещи, которые должны были быть в ядре", такие как https://weavejester.github.io/medley/medley.core.html. Быстрый поиск на https://crossclj.info/ показывает, что https://github.com/amalloy/useful содержит flatland.useful.seq / unfold, который, хотя я и не использовал, выглядит отличной реализацией для основного разработчика Clojure. и поставляется с некоторыми другими классными вещами для загрузки.

Другие вопросы по тегам