Clojure where is left fold
Clojure是否实现左折或右折?
我知道有一个新的带有这个功能的库缩减器,但它不应该存在于clojure.core中吗?
Clojure实现了称为reduce的左折。
为什么没有对折?
-
reduce和许多其他函数可用于序列,这些序列是
可从左侧访问,但不能从右侧访问。
新的异径管和换能器旨在与可访问性不同的数据结构上的关联功能配合使用。
-
您无需从右侧访问序列即可实现右折叠:(defn reduce-right [f init xs] (if-let [xs (seq xs)] (f (first xs) (reduce-right (rest xs) f init)) init))。
-
@ sepp2k是的,您可以通过这种方式实现右折叠,但是JVM以及因此Clojure(具有相当有限的堆栈空间)没有足够的能力来处理长序列的递归。 例如,(reduce-right max -1 (range 10000))在此处引起堆栈溢出-YMMV。 [为了获得此结果,我更正了您的函数以一致地调用自身,并借此机会对其进行了一些简化:(defn reduce-right [f init xs] (if (seq xs) (f (first xs) (reduce-right f init (lazy-seq (rest xs)))) init))。]
正如Thumbnail指出的那样,不能在序列的jvm上有效地实现reduce-right。 但事实证明,我们确实有一系列数据类型,它们可以从右侧进行有效的查找和截断。 向量可以实现reduce-right。
1 2 3 4 5 6 7 8 9 10 11
| user>
(defn reduce-right
[f init vec]
(loop [acc init v vec]
(if (empty? v)
acc
(recur (f acc (peek v)) (pop v)))))
#'user/reduce-right
user> (count (str (reduce-right *' 1 (into [] (range 1 100000))))) ; digit count
456569 |
-
根据peek和pop的运算位置,这在矢量上执行右折叠,但在列表上执行左折叠:(reduce-right (fn [_ x] x) :init (vec (range 10))) => 0; (reduce-right (fn [_ x] x) :init (apply list (range 10))) => 9。
-
是的,完全不是要列出清单。 我猜可能需要一个前提条件。