A bit of Clojure magic and high order functions are served

Hi guys, what’s up?

I’m a little busy right now. I’ve started what is probably going to be my last semester of university courses and I’ve started coding a Clojure 3D library (coming soon on these screens). But this is the good time to take a break and write something on this blog. A really cool (and useful) features of Haskell is the ability to use High Order Functions. Take a look to this simple Haskell snippet:

> :t take
take :: Int -> [a] -> [a]

> :t take 10
take 10 :: [a] -> [a]

> :t take 10 ['a'..'z']
take 10 (enumFromTo 'a' 'z') :: [Char]

As you can see the arguments are “eaten” one by one in a way that remember the dear old Pacman. In a nutshell take 10 returns a function that applied to a sequence return a result. Simple enough, isn’t it?
Unfortunately this doesn’t happens by default in Clojure. Observe this little function:

(defn sum [a b] (+ a b))

If you’ll try to invoke

(sum 1)

you we’ll get the following:

Wrong number of args (1) passed to: user$sum

This is absolutely normal, since it is the Clojure default behaviour. Googling and Stack-overflowing around a bit, I came up to a simple snippet to implement with a macro the required behaviour:

(defmacro defn-decorated
  "like defn except it accepts an additional vector of
   decorator functions which will be applied to the base definition.
   the decorators are applied in left-to-right order."
  {:author "Robert McIntyre"
   :arglists '[[name [modifers*] doc-string? attr-map? [params*] body]
	       [name [modifers*] doc-string? attr-map? ([params*] body) + attr-map?]]}
  [fn-name decorators & defn-stuff]
  `(do
     (defn ~fn-name ~@defn-stuff)
     (alter-var-root (var ~fn-name) (reduce comp identity (reverse ~decorators)))
     (var ~fn-name)))

(defn curry**
  [number-of-args f]
  (fn
    ([& args]
       (let [number-of-inputs (count args)]
	 (if (= number-of-inputs number-of-args)
	   (apply f args)
	   (curry** (- number-of-args number-of-inputs)
		    (apply (partial+ partial+ f) args)))))))

(def curry* (curry** 2 curry**))

(By the way you can find the complete clj file here.) Here’s an example of application:

(defn-decorated sum [(curry 2)] [a b] (+ a b))

But a thing I didn’t like was the explicit passing of the number of argument which the function is composed, so I wrote my own macro:

(defmacro defn-ho
  [fn-name & defn-stuff]
  (let [number-of-args (count (first defn-stuff))]
    `(defn-decorated ~fn-name [(curry* ~number-of-args)] ~@defn-stuff)))

With this simple add-on, you can easily write any kind of high order function in a way like this:

(defn-ho new-sum [a b c] (+ a b c))

I haven’t tried it in particular situations (e.g. with destructuring) but don’t expect it to work with function with multiple arity: indeed, but really  you will need to create n-arity high order function??

Feedback are welcome, as always!

Cheers!

Alfredo