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

Annunci

The power of the big

Wow…

I’ve been quoted into a sort of report about F# and XNA development (Btw, I’ve only tweaked a bit a source code found on the net, just to learn a bit F# and XNA):

http://geekswithblogs.net/clingermangw/archive/2011/01/28/143679.aspx

I’m really surprised due to the echo of F# and XNA all over the internet… I mean, I’ve spent hours playing and writing about other awesome functional languages (Haskell, Scheme, Common Lisp, Clojure) but I’ve never been quoted, because “Speaking about Common Lisp and other crazy stuff is not cool”. This is sad, really sad.

On the other side, I’m very proud of have been cited somewhere 😛 (despite I haven’t done nothing special)

Bye,

Alfredo