Welcome! Please see the About page for a little more info on how this works.

+4 votes
in Clojure by

There are places in code where I need functions that I define and use only once, in the same place I define them. There are 2 main ways to define such functions, one is anonymous fns:
(map #(blepify-with blep (:blop %)) xs)
Another is higher order functions:
(map (comp (partial blepify-with blep) :blop) xs)

I personally don't use partial, and always prefer anonymous functions, because:

  • anonymous functions go through var dereference on invokation, which means I can redefine blepify-with and new definition is used automatically. It helps greatly during development, and just as performant in production with direct linking;
  • partial makes code less readable by hiding function arity. Explicit is better than implicit, and Cursive can show me immediately if I pass wrong amount of arguments to function

I also rarely use comp. In addition to same argument about var dereferencing, it makes me read code from right to left. On small examples I provided it does not really matter, but as it grows bigger, threading macros greatly enhance readability.
They only time I find comp useful is when inversed order of function application is negated by inverse order of data processing, such as transducers: (comp (filter even?) (map inc)) is intended to be read from left to right. Even though (map inc) is invoked first, data processed by this transducer will first go through even? predicate, and then through inc transform.

My question is, is there something more to partial and comp that I'm missing? Maybe it's a matter of taste and I'm just not used to them, and they are just as readable, and not having to redefine usage places is overrated? When should I prefer comp and partial to anonymous functions?

2 Answers

+7 votes

In my opinion, you should prefer anonymous functions to partial and comp and that is the idiomatic solution for Clojure.

The only time I use comp is when composing transducer chains. I almost never use partial.

+3 votes

I find myself refactoring comp and partial to be fn, letfn or #() statements. The result can be more verbose but easier to reason about and debug.

Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by
definition, not smart enough to debug it.

— Kernighan’s law

My preference is to avoid being too clever or obsessing over code brevity to the exclusion of other considerations.

As others have said, anonymous functions are far more common, but I do sometimes use partial. I rarely use comp, typically only for transducers because it makes the application order easier to understand; otherwise, I use the threading macros. I will only use partial if the application is extremely straightforward, where I have all but the last parameter of a function application and I need to use that in a high order function. Keep it simple and straightforward.
Welcome to Clojure Q&A, where you can ask questions and receive answers from members of the Clojure community.