Clojure有“unfold”吗?

4
(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个回答

4
不,Clojure中没有实现"unfold"。该功能是由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核心贡献者提供的很棒的实现,并且还带有其他很酷的东西。

我忘记了是什么激励我提出了这个问题,但我只是想更好地了解如何编写适用于此类任务的习惯用语Clojure。我认为您的答案在提供我所寻找的信息方面做得很好。 - Dan Burton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接