我们可以看到我们可以使用reduce
/foldl1
作为函数,通过它我们可以定义其他高阶函数,例如 map、filter 和 reverse。
(defn mapl [f coll]
(reduce (fn [r x] (conj r (f x)))
[] coll))
(defn filterl [pred coll]
(reduce (fn [r x] (if (pred x) (conj r x) r))
[] coll))
(defn mapcatl [f coll]
(reduce (fn [r x] (reduce conj r (f x)))
[] coll))
我们似乎也能够做到这一点foldr
。这里是来自Rich Hickey在 17:25map
的Transducers 演讲。filter
foldr
(defn mapr [f coll]
(foldr (fn [x r] (cons (f x) r))
() coll))
(defn filterr [pred coll]
(foldr (fn [x r] (if (pred x) (cons x r) r))
() coll))
现在事实证明,有一些论文可以解释这一点:
BIRD - 构造函数式编程讲座 - 1988 https://www.cs.ox.ac.uk/files/3390/PRG69.pdf
HUTTON - 关于 fold 的普遍性和表现力的教程 - 1999 http://www.cs.nott.ac.uk/~gmh/fold.pdf
这周我听到有人说:
Well
flatmap
(mapcat
) 是基本的——你可以用它来表达很多高阶函数。
所以这里是map
按照mapcat来实现的。
=> (defn mymap [f coll] (mapcat (comp vector f) coll))
=> (mymap #(+ 1 %) (range 0 9))
(1 2 3 4 5 6 7 8 9)
但对我来说,这感觉很不自然,因为您实际上只是在打量事物并确定地图本身是否是“基本的”。
最后一个例子感觉有点人为的原因是 mapcat 已经根据 map 进行了定义。如果您查看mapcat 的源代码- 我们会看到类似以下内容:
(defn mapcat
[f & colls]
(apply concat (apply map f colls)))
所以上面的例子只是颠倒了 concat 并重用了 mapcat 内部的 map 的底层定义——这对我来说是人为的。现在如果可以使用 mapcat 来定义其他 HOF 就可以了——但我不知道该怎么做——我希望有人能指出我的方向。
我的问题是:flatmap/mapcat 是一个可以用作其他高阶函数基础的函数吗?