0

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 filterHickeyfoldrの 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) は基本です。これを使って多くの高階関数を表現できます。

したがって、ここではmapmapcatの観点から実装されています。

=> (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 は他の高次関数の基礎として使用できる関数ですか?

4

1 に答える 1