In a 1988 paper called Algebraic Identities for Program Calculation, Richard Bird wrote:

Probably the most useful law about map is the fact that it distributes over functional composition: (map f) . (map g) = map (f . g)

``````GHCi, version 6.12.1: http://www.haskell.org/ghc/  :? for help
Prelude> let f x = x * x
Prelude> let g x = x + 1

Prelude> ((map f) . (map g)) [1 .. 5]
[4,9,16,25,36]

Prelude> map (f.g) [1 .. 5]
[4,9,16,25,36]
``````

I am a sucker for nice notation, and that is some very nice notation. It got me thinking about how I might write the same thing in Clojure. Here is my first cut at a literal translation:

``````user> ((comp (partial map sq) (partial map inc)) (range 1 6))
(4 9 16 25 36)

user> (map (comp sq inc) (range 1 6))
(4 9 16 25 36)``````

The Clojure code looks a little noisy by comparison, mostly due to the explicit use of partial. I came up with a couple of variations on map that clean up the presentation. The first I call mapp:

``````(defn mapp
([f] (partial map f))
([f x & args]
(apply map (partial f x)
args )))``````

Here are some examples of mapp in action:

``````;; Using regular old map
user> ((comp (partial map sq) (partial map inc)) (range 1 6))
(4 9 16 25 36)

;; We can clean that up a bit with mapp
user> ((comp (mapp sq) (mapp inc)) (range 1 6))
(4 9 16 25 36)

;; Or you can do stuff like this
user> (mapp * 100 (range 6))
(0 100 200 300 400 500)

user> (mapp + 1/2 (range 6))
(1/2 3/2 5/2 7/2 9/2 11/2)``````

My other variation on map is called mapc.

``````(defn mapc [& args]
(let [[fns xs] (partition-by fn? args)
g (apply comp fns)]
(if (empty? xs)
(partial map g)
(apply map g xs ))))``````

Here are some examples of mapc in action.

``````;; Map the (implicit) composition of two functions
user> (mapc sq inc (range 1 6))
(4 9 16 25 36)

;; We can compose more than two functions
user> (mapc inc sq inc (range 1 6))
(5 10 17 26 37)

;; Or use mapc like plain old map
user> (mapc sq (range 1 6))
(1 4 9 16 25)

;; Or by providing only functional args, produce a function
user> ((mapc sq inc) (range 1 6))
(4 9 16 25 36)``````

To wrap this up, note that I wanted to come close to something like

``(map f) . (map g) = map (f . g)``

The best I could do was

``(comp (mapp f) (mapp g))  =  (mapc f g) ``

That’s not half bad. I rather like mapp and mapc. But I genuinely wonder whether anyone else will. Play around with mapp and mapc, let me know what you think.

Update: In the comments, MarkusQ pointed out that (comp (mapp f) (mapp g)) = (mapp (comp f g)). In particular,

``````user> ((comp (mapp sq) (mapp inc)) (range 1 6))
(4 9 16 25 36)

user> ((mapp (comp sq inc)) (range 1 6))
(4 9 16 25 36)``````

MarkusQ’s equation preserves symmetry by using mapp on both side of the equals sign. I think this is much prettier than the version I came up with. Keats observed that “Beauty is truth, truth beauty…”. The version Markus sent in makes me believe that mapp may well be a worthwhile abstraction.