map 、 filter 、 reverse などの他の高次関数を定義できる関数としてreduce
/を使用できることがわかります。foldl1
(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
。これはmap
、 Rich filter
Hickeyfoldr
の Transducers トークの 17:25 からです。
(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 - フォールドの普遍性と表現力に関するチュートリアル - 1999 http://www.cs.nott.ac.uk/~gmh/fold.pdf
さて、今週誰かが言うのを聞いた:
まあ
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 は他の高次関数の基礎として使用できる関数ですか?