0

We can see that we can use reduce/foldl1 as the function by which we can define other higher order functions such as map, filter and 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))

We also appear to be able to do this in terms of foldr. Here is map and filter in terms of foldr from Rich Hickey's Transducers talk at 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))

Now it turns out there are some papers that explain this:

BIRD - Lectures on Constructive Functional Programming - 1988 https://www.cs.ox.ac.uk/files/3390/PRG69.pdf

HUTTON - A tutorial on the universality and expressiveness of fold - 1999 http://www.cs.nott.ac.uk/~gmh/fold.pdf

Now I heard somebody say this week:

well flatmap (mapcat) is fundamental - you can express lots of higher order functions in terms of it.

So here is map implemented in terms of mapcat.

=> (defn mymap [f coll] (mapcat (comp vector f) coll))

=> (mymap #(+ 1 %) (range 0 9))

(1 2 3 4 5 6 7 8 9)

But to me that feels artificial since you're really just boxing things and working out whether map itself is 'fundamental'.

The reason this last example feels a little artificial is that mapcat is already defined in terms of map. If you look at the source for mapcat - we see something similar to:

(defn mapcat
  [f & colls]
    (apply concat (apply map f colls)))

So the example above merely reverses out the concat and reuses the underlying definition of map inside of mapcat - which to me feels artificial. Now it would be ok if mapcat could be used to define other HOFs - but I don't know how to do that - and I'm hoping someone can point me in that direction.

My question is: Is flatmap/mapcat a function that can be used as the basis of other higher order functions?

Community
  • 1
  • 1
hawkeye
  • 34,745
  • 30
  • 150
  • 304

1 Answers1

0

map is a primitive used to create mapcat.

You can use mapcat to create map which is reducing mapcat back to the map it was built from.

You can build an infinite amount of higher order functions using both.

Leon Grapenthin
  • 9,246
  • 24
  • 37