I'm currently writing functions with undefined number of arities and I so looked for examples in clojure.core and so on.
This is for example the definition of comp (clojure.core)
(defn comp
"Takes a set of functions and returns a fn that is the composition
of those fns. The returned fn takes a variable number of args,
applies the rightmost of fns to the args, the next
fn (right-to-left) to the result, etc."
{:added "1.0"
:static true}
([] identity)
([f] f)
([f g]
(fn
([] (f (g)))
([x] (f (g x)))
([x y] (f (g x y)))
([x y z] (f (g x y z)))
([x y z & args] (f (apply g x y z args)))))
([f g & fs]
(reduce1 comp (list* f g fs))))
As you can see, for the arities [f g], the code detail the values for 2 and 3 arguments (x y ; x, y, z) even if it could just have directly jumped to [x & args].
Is there any performance reason ? Or is it a convention ?
I suppose that calling apply could impact performance, I don't know.
We generally use at most 3D functions and composition of 2 functions in real lif, maybe it's because of that.
Thanks
Clojure's core library is implemented often in ways that are not particularly idiomatic, specifically for performance reasons. If you are writing a function that is going to be fundamental to most of the lines of code in your program, you could do the same, but in general this is not elegant or particularly advised.
Related
Is it possible to write a define-values macros in Clojure?
Racket language provides such a thing like define-values form which acts in this way
(define -values '(a b c) (1 2 3))
Where a, b, c are global variables now.
How can I do it in Clojure?
(defmacro defvar [x y]
`(let [a# ~x
b# ~y]
(def b# a#)))
(println (defvar 'a 2))
=> #'user/b__2__auto__
;;;It binds the value to auto generated symbol
define-values doesn't make any sense in Clojure. It makes sense in Racket because values lets one expression evaluate to multiple values. In Clojure, an expression always evaluates to exactly one value: there's no values to extract into definitions.
Of course, you can write a macro def-several-things such that
(def-several-things [x y] [1 2])
expands to
(do (def x 1)
(def y 2))
but this is less readable, not more, so nobody does it.
This question already has an answer here:
Why such implementation of partial in clojure.core
(1 answer)
Closed 6 years ago.
I'm a beginner in clojure trying to understand it at a basic level for now.
I've been experimenting with partial and how it creates closures, and to get a deeper understanding I thought I should take a peek at the source code by doing a (source partial) .
There I get
(defn partial
"Takes a function f and fewer than the normal arguments to f, and
returns a fn that takes a variable number of additional args. When
called, the returned function calls f with args + additional args."
{:added "1.0"
:static true}
([f] f)
([f arg1]
(fn
([] (f arg1))
([x] (f arg1 x))
([x y] (f arg1 x y))
([x y z] (f arg1 x y z))
([x y z & args] (apply f arg1 x y z args))))
([f arg1 arg2]
(fn
([] (f arg1 arg2))
([x] (f arg1 arg2 x))
([x y] (f arg1 arg2 x y))
([x y z] (f arg1 arg2 x y z))
([x y z & args] (apply f arg1 arg2 x y z args))))
([f arg1 arg2 arg3]
(fn
([] (f arg1 arg2 arg3))
([x] (f arg1 arg2 arg3 x))
([x y] (f arg1 arg2 arg3 x y))
([x y z] (f arg1 arg2 arg3 x y z))
([x y z & args] (apply f arg1 arg2 arg3 x y z args))))
([f arg1 arg2 arg3 & more]
(fn [& args] (apply f arg1 arg2 arg3 (concat more args)))))
I find the whole definition to be redundant as I would only write it in a "varargs" fashion, ie the last 2 lines.
Is this a readability feature or am I missing something basic here?
It's not a readability feature but a matter of performance. Stuart Sierra explained it in Clojure Don’ts: Optional Arguments with Varargs:
Variable-arity function calls have to allocate a sequence to hold the arguments, then go through apply. Timothy Baldridge did a quick performance comparison showing that calls to a function with multiple, fixed arities can be much faster than variable-arity (varargs) function calls.
In that benchmark, the varargs version with 1 argument is around an order of magnitude slower than the multi-arity version with 1 arg, and with 3 args the difference goes up to ~ 2 orders of magnitude.
This is not to say that varargs should not be used at all: Sparsely calling a fn with varargs will probably not affect performance, but it could hit you hard when calling it from a tight loop.
I find the whole definition to be redundant as I would only write it
in a "varargs" fashion,
You are quite right. All but the varargs definition are redundant. As #nberger points out, the others are there to improve performance. You will find many such in clojure core: such as map, max, and comp.
This question already has an answer here:
Why such implementation of partial in clojure.core
(1 answer)
Closed 6 years ago.
Goal
I'm trying to understand how transducers are implemented.
Confusion
I'm looking at comp, implement here.
In particular, these lines here:
([] (f (g)))
([x] (f (g x)))
([x y] (f (g x y)))
([x y z] (f (g x y z)))
([x y z & args] (f (apply g x y z args)))))
Now, what I don't understand -- why are there five cases? Could this not have been rewritten as:
(args (f (apply g args)))
?
Is there any particular reason why the code was written as above?
Could this not have been rewritten as (args (f (apply g args)))?
Yes, but this has nothing to do with transducers.
comp performs functional composition, whether or not the function
arguments are transducers.
Many core functions, including comp, specialise simple cases for speed.
The general question, as #ClojureMostly notes, is answered here.
This is an extension to my previous question here.
The purpose is demonstrated as below:
(defn foo
[x a-map]
(assoc a-map x "value"))
(defn -main
[x]
(let [[x1 x2 x3 ... xn] x]
(-> {}
(partial foo x1)
(partial foo x2)
(partial foo x3)
...
(partial foo xn))))
The complexity of this problem lies that I have to populate a variable number of partial functions so I cannot use -> nor 'comp'. The real mechanism of the foo function is not an assoc of course so I cannot simplify the problem as a zipmap.
I'm not sure if this matter, but the input argument x is actually a cartesian product of two sequences. So each element of x is a two-element vector that iterates through the cartesian product space of two sequences. It is generated using a for loop, or rather, list comprehension.
What do you suggest to handle this problem? Let me know if I failed to give some important info.
Cheers
First of all, your usage of thread first -> macro is incorrect (see this question for more info). Here is the right syntax using thread last ->> macro:
(->> {}
(foo x1)
(foo x2)
(foo x3)
(foo x4))
Though, it won't work unless the length of vector x is determent.
But you could use reduce function here to process any sequence of elements:
(reduce #(assoc %1 %2 "value") {} x)
Here is a complete example (with slightly redefined foo function):
(defn foo
[a-map x] ; reversed order of arguments
(assoc a-map x "value"))
(defn -main
[x]
(reduce foo {} x))
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?
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.
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?
This will allow you to do what you want:
(defn curry
([f len] (curry f len []))
([f len applied]
(fn [& more]
(let [args (concat applied (if (= 0 (count more)) [nil] more))]
(if (< (count args) len)
(curry f len args)
(apply f args))))))
Here's how to use it:
(def add (curry + 2)) ; read: curry plus to 2 positions
((add 10) 1) ; => 11
The conditional with the [nil] is meant to ensure that every application ensures some forward progress to the curried state. There's a long explanation behind it but I have found it useful. If you don't like this bit, you could set args as:
[args (concat applied more)]
Unlike JavaScript we have no way of knowing the arity of the passed function and so you must specify the length you expect. This makes a lot of sense in Clojure[Script] where a function may have multiple arities.