Examples of Clojure arity-overloading on functions like the following (taken from the cookbook):
(defn argcount
([] 0) ; Zero arguments
([x] 1) ; One argument
([ x & args] (inc (count args)))) ; List of arguments
... use a form that doesn't seem to allow the functions of lower arity to simply call the functions of higher arity with some default values (that's a common idiom in Java). Is some other special form used for that ?
There's usually a good way to express the higher arity arguments in a way that doesn't need to refer to other arities using higher order functions and map
/ reduce
. In this case it's pretty simple:
(defn argcount
([] 0)
([x] 1)
([x & args]
(reduce + 1 (map (constantly 1) args))))
Notice the general form of the expression is:
(reduce reducing-function arity-1-value (map mapping-function rest-of-args))
You can't do everything this way, but this works for a surprisingly large proportion of multi-argument functions. It also gains the advnatages of laziness using map
, so you can do crazy things like pass ten million arguments to a function with little fear:
(apply argcount (take 10000000 (range)))
=> 10000000
Try that in most other languages and your stack will be toast :-)
mikera's answer is awesome; I'd just add an additional method. When the a default value is needed for an overloaded function, a local can be used.
In the example division below, the local requires numbers and precision. The defined function overloads the precision with a default value.
(def overloaded-division
(let [divide-with-precision
(fn [divisor dividend precision]
(with-precision precision (/ (bigdec divisor) (bigdec dividend))))]
(fn
;lower-arity calls higher with a default precision.
([divisor dividend] (divide-with-precision divisor dividend 10))
;if precision is supplied it is used.
([divisor dividend precision] (divide-with-precision divisor dividend precision)))
)
)
When called at lower-arity, the default it applied:
user=> (overloaded-division 3 7)
0.4285714286M
user=> (overloaded-division 3 7 40)
0.4285714285714285714285714285714285714286M
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