Over the next week or so, I'd like to talk about Clojure's function composition functions in a series of small and focused posts: Clojure Composers.
Today, I'll just discuss some composer basics.
About
Function composers provide us moulds with which we may create other functions. If we were to put this in mathematical terms, a function composer is a function f(x)
that returns g(y)
.
This is great for us because rather than writing something like this...
(map #(some complicated (code %)) stuff)
...we can have a composer that looks like this...
(defn complicator [f]
(fn [thing] (some complicated (f thing))))
...then write this!
(map (compliator code) stuff)
Giving us a clean way of hiding the ugly stuff behind the stuff we care about.
Anatomy
There are a couple characteristics that apply to all composers, and I'll use Clojure's simplest composer, constantly
, as an example.
(defn constantly [x]
(fn [& args] x))
Parameters
A composer will take one or more arguments, and use them in some way to build out a function. In the case above, constantly
accepts only one parameter. However, other composers such as juxt
or comp
can take any number of arguments.
If a composer takes zero arguments, then it should either be a constant or it depends on something externally from the function.
Return Value
We can assume the return value will always be a function, which may have any arity (usually consistent with some defined pattern). Zero, one, two, infinite... In the example above, constantly
always returns a function that accepts any number of arguments.
Conclusion
While we can use composers just about anywhere, I find that they really shine in functions like map
, filter
, or sort-by
where there is usually already some chaining of functions happening.
Which of these do you find easier to read?
(map #(-> % :kills :confirmed) kittens)
(filter #(-> % :kills :confirmed zero?) kittens)
(sort-by (fn [{:keys [age weight]}] [age weight]) kittens)
(map (comp :confirmed :kills) kittens)
(filter (comp zero? :confirmed :kills) kittens)
(sort-by (juxt :age :weight) kittens)
Top comments (0)