# A clj snippet #3

Today's snippet comes from a small clojure contrib library called `algo.generic`

. The library helps to extend standard `clojure.core`

functions to your own types. These extensions are implemented via multimethods.

`{:deps`

` {compliment {:mvn/version "0.3.10"}`

` org.clojure/algo.generic {:mvn/version "0.1.3"}}} `

`(use [clojure.algo.generic.functor])`

`(fmap inc {:a 1 :b 2 :c 3})`

`fmap`

behaves like map but returns the result as the same type as the input structure. As you can see above, for maps the mapping function is applied to the values. `fmap`

unlike `map`

only works on one collection. Let's create a version called `fmap*`

that works on more than one collection and which asserts that every collection has the same type.

`(defmulti fmap* (fn [f & colls]`

` (assert (apply = (map type colls)))`

` (type (first colls))))`

`(defmethod fmap* clojure.lang.PersistentVector`

` [f & colls]`

` (into [] (apply map f colls)))`

`(fmap* + [1 2 3] [1 2 3 4] [1 2 3 4 5])`

Now, lets put `fmap*`

to some use and extend some standard operators.

`(require [clojure.algo.generic.arithmetic :as generic])`

`;; elementwise plus `

`(defmethod generic/+`

` [clojure.lang.PersistentVector clojure.lang.PersistentVector]`

` [x y]`

` (fmap* + x y))`

`(defmethod generic/+`

` [java.lang.Long clojure.lang.PersistentVector]`

` [x y]`

` (fmap (partial + x) y))`

`;; dot product`

`(defmethod generic/*`

` [clojure.lang.PersistentVector clojure.lang.PersistentVector]`

` [x y]`

` (fmap* * x y))`

`(use clojure.algo.generic.arithmetic)`

`(+ 42 [1 2 3] (* [1 2 3 4] [1 2 3 4 5]))`

The nice thing about `alog.generic`

is that it automatically gives you variadic versions if you implemented the binary version of an operator because the default method for the `nary`

version of `+`

looks as follows:

`(defmethod + nary-type ;; a dispatch value defined by algo.generic `

` [x y & more]`

` (if more`

` (recur (+ x y) (first more) (next more))`

` (+ x y)))`

As you realize now `fmap*`

was actually not really needed to implement the extension for the arithmetic operators, we could just as easy done something like

`(into [] (map + [1 2 3] [4 5 6]))`

in the `genereic/+`

.

Still, with `fmap*`

you are able to quickly map functions or combine them if you haven't yet written a generic extension for them

`(defn exp [x n]`

` (reduce * (repeat n x)))`

`(fmap* (fn [x y z] (exp x (exp y z))) [1 2 3] [1 2 3] [1 2 3])`