Currying in Lispz

Functional programmers love currying for some reason. [Haskell Brooks Curry]( was an American mathematician who lived through the first 80 years of the 20th century. So, _currying_ is named after a person and is not a description – except possibly that it spices up your code :). Currying is the epitome of a higher level function. You supply it with a function that has a fixed list of parameters. It returns a function that can be called with less parameters. Until all the parameters are supplied, the curried function returns another function. You will probably get a better explanation here: Better still, an example. In Lispz, _curry_ behaves like _lambda_ while providing the additional functionality…

(ref add-3 (curry [a b c] (+ a b c)))

(add-3 1 2 3) ## ==> 6; is the same as
(((add-3 1) 2) 3) ## is the same as
((add-3 1 2) 3)

This doesn’t look very useful (probably because it isn’t). Here is a simple use of currying where both _first_ and _second_ are functions that return the appropriate entry when given an array.

(global dot (curry [index array] (#join '' '(_res_=' array '[' index '])')))
(global first (dot 0))
(global second (dot 1))

There are also functions for third, fourth and last. It is a way to make your code more declarative, but is nothing more than a convenience. I could have written

(global first (lambda [array] (get array 1)))

You will soon recognise code from functional programmers who favour currying. Their functions will be defined with the parameters in an unusual order so that the parameters likely to change are at the end. If you are lucky enough to have a function with two parameters you can reverse the order. Pull is curried, so we can use it to create a new function that knows about a stateful cache and can retrieve items by name.

(global get-from (flip

(ref commands {a: 1 b: 2 c: 3})
(ref command (get-from commands))
(command "b")

I do not use currying a lot, preferring explicit definitions, but when it is useful it is very useful. The following example keeps a cache of arrays accessed by name. When a new name is used a new array is created.

(global stateful.cache (curry [store update key]
  (or (get store key) (do (store.update! key (update)) (get store key)))
## ... much later
(ref exchange (stateful))
(ref observers (stateful.cache exchange (=> (stateful []))))
## ...
((observers "my-key").push! my-value)

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s