Clojure is awesome, we all know this, but that's not the point. I'm wondering what the idiomatic way of creating and managing higher-order functions in a Haskell-like way is. In Clojure I can do the following:
(defn sum [a b] (+ a b))
But (sum 1)
doesn't return a function: it causes an error. Of course, you can do something like this:
(defn sum ([a] (partial + a)) ([a b] (+ a b)))
In this case:
user=> (sum 1) #<core$partial$fn__3678 clojure.core$partial$fn__3678@1acaf0ed> user=> ((sum 1) 2) 3
But it doesn't seem like the right way to proceed. Any ideas?
I'm not talking about implementing the sum
function, I'm talking at a higher level of abstraction. Are there any idiomatic patterns to follow? Some macro? Is the best way defining a macro or are there alternative solutions?
Higher order functions are functions that operate on other functions, either by taking them as arguments or by returning them. In simple words, A Higher-Order function is a function that receives a function as an argument or returns the function as output. For example, Array. prototype.
First Class Functions They can be assigned as values, passed into functions, and returned from functions. It's common to see function definitions in Clojure using defn like (defn foo … ) . However, this is just syntactic sugar for (def foo (fn … )) fn returns a function object.
Higher-Order Functions(HoF): A function that takes another function(s) as an argument(s) and/or returns a function as a value. Callback Functions(CB): A function that is passed to another function.
Higher Order Function In functional programming, a function is defined as a "first order citizen". This means it includes all the properties generally available to any other element, such as the possibility of being affected to a name, returned as a result or passed as a parameter.
I've played a bit with the functions suggested by amalloy. I don't like the explicit specification of the number of argument to curry on. So I've created my custom macro. This is the old way to specific an high order function:
(defn-decorated old-sum [(curry* 3)] [a b c] (+ a b c))
This is my new 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)))
And this is the new implicit way:
(defn-ho new-sum [a b c] (+ a b c))
As you can see there is no trace of (curry) and other stuff, just define your currified function as before.
Guys, what do you think? Ideas? Suggestions? Bye!
Alfedo
Edit: I've modified the macro according the amalloy issue about docstring. This is the updated version:
(defmacro defhigh "Like the original defn-decorated, but the number of argument to curry on is implicit." [fn-name & defn-stuff] (let [[fst snd] (take 2 defn-stuff) num-of-args (if (string? fst) (count snd) (count fst))] `(defn-decorated ~fn-name [(curry* ~num-of-args)] ~@defn-stuff)))
I don't like the if statement inside the second binding. Any ideas about making it more succint?
Someone has already implememented this on the Clojure group. You can specify how many args a function has, and it will curry itself for you until it gets that many.
The reason this doesn't happen by default in Clojure is that we prefer variadic functions to auto-curried functions, I suppose.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With