In clojure, calling reduce * on en empty collection returns 1. This is quite surprising.
I made this discovery while creating a factorial function, defined as follow :
(defn factorial [n] (reduce * (take-while #(> % 0) (iterate dec n))))
(factorial 0) is correctly returning 1, without me having to write a special case for zero.
How come ?
Checking the code for * and + shows that these two functions implement the 0-arity case by returning the identity for the operation. In the case of * the code is (with dosctring and metadata removed):
(defn *
([] 1)
([x] (cast Number x))
([x y] (. clojure.lang.Numbers (multiply x y)))
([x y & more]
(reduce1 * (* x y) more)))
The main point here is the behaviour of reduce. In
(reduce f s)
... if s is empty, the call returns (f).
Since (*) is 1,
(reduce * ())
; 1
reduce doesn't care that 1 is the identity for *. Though 1 is also the right identity for /,
(reduce / ())
; ArityException Wrong number of args (0) passed to: core$-SLASH- ...
... because, as it happens, / does not declare a 0 arity version.
Related
I'm trying to estimate the mean distance of all pairs of points in a unit square.
This transducer returns a vector of the distances of x randomly selected pairs of points, but the final step would be to take the mean of all values in that vector. Is there a way to use mean as the final reducing function (or to include it in the composition)?
(defn square [x] (* x x))
(defn mean [x] (/ (reduce + x) (count x)))
(defn xform [iterations]
(comp
(partition-all 4)
(map #(Math/sqrt (+ (square (- (first %) (nth % 1)))
(square (- (nth % 2) (nth % 3))))))
(take iterations)))
(transduce (xform 5) conj (repeatedly #(rand)))
[0.5544757422041136
0.4170515673848907
0.7457675423415904
0.5560901974277822
0.6053573945754688]
(transduce (xform 5) mean (repeatedly #(rand)))
Execution error (ArityException) at test.core/eval19667 (form-init9118116578029918666.clj:562).
Wrong number of args (0) passed to: test.core/mean
If you implement your mean function differently, you won't have to collect all the values before computing the mean. Here is how you can implement it, based on this Java code:
(defn mean
([] [0 1]) ;; <-- Construct an empty accumulator
([[mu n]] mu) ;; <-- Get the mean (final step)
([[mu n] x] ;; <-- Accumulate a value to the mean
[(+ mu (/ (- x mu) n)) (inc n)]))
And you use it like this:
(transduce identity mean [1 2 3 4])
;; => 5/2
or like this:
(transduce (xform 5) mean (repeatedly #(rand)))
;; => 0.582883812837961
From the docs of transduce:
If init is not supplied, (f) will be called to produce it. f should be
a reducing step function that accepts both 1 and 2 arguments, if it
accepts only 2 you can add the arity-1 with 'completing'.
To disect this:
Your function needs 0-arity to produce an initial value -- so conj
is fine (it produces an empty vector).
You need to provide a 2-arity function to do the actual redudcing
-- again conj is fine here
You need to provide a 1-arity function to finalize - here you want
your mean.
So as the docs suggest, you can use completing to just provide that:
(transduce (xform 5) (completing conj mean) (repeatedly #(rand)))
; → 0.4723186070904141
If you look at the source of completing you will see how it produces
all of this:
(defn completing
"Takes a reducing function f of 2 args and returns a fn suitable for
transduce by adding an arity-1 signature that calls cf (default -
identity) on the result argument."
{:added "1.7"}
([f] (completing f identity))
([f cf]
(fn
([] (f))
([x] (cf x))
([x y] (f x y)))))
I have a simple function that adds numbers together and multiplies them.
(defn add-and-multiply [x y z]
(let [add (+ x y z)
mult (* x y z)]
(println "Add: " add)
(println "Mult: " mult)))
(add-and-multiply 1 1 2)
Add: 4
Mult: 2
nil
How would I call add-and-multiply again with the x argument now being the result of add (4), the y argument being the result of mult (2) and the z argument being the same (2).
How could I then repeat this process 100 times and then print the final values of add and mult?
Any help would be much appreciated. Thanks
I would not be surprised to find that the result after 100 iterations is too large to fit into RAM. Unless I am misunderstanding the formula, this is a lot like computing x*(x^2)*(x^4)*(x^8)...up to x^(2^100), which simplifies to x^(2^200). It's actually larger because there is an adding step as well, but I think that is relatively minor compared to the iterative multiplication. 2^200 is pretty big already, but you could compute it if you needed to.
However, 2^(2^200) is tremendously vast. Obviously you need 2^200 bits of RAM, at a minimum, to hold that number without losing precision. A typical desktop computer has perhaps 16GB of RAM, which is 2^30 (a billion) * 16 gigs * 8 bits/byte = 2^37 bits of storage. You would need not just one desktop computer to store this, but 2^163 of them. Again, I cannot emphasize enough just how large a number that is. If every grain of sand on the planet were a desktop computer with 16GB of RAM, you would not be close to being able to store this number.
So, I would say you should probably figure out a different way to solve whatever your real problem is, assuming you can't afford to buy whole galaxies worth of computing power.
That said, regarding the mechanics of how to generalize (f (f (f (f x)))) to an arbitrary number of calls to f, the other answers have given you a good explanation of how to use iterate, and will serve you well if you choose an f whose runtime is more manageable.
If you change add-and-multiply to return the two results:
(defn add-and-multiply [x y z]
(let [add (+ x y z)
mult (* x y z)]
[add mult]))
then you can use iterate to generate successive applications. Use first and drop to select the result you want e.g.
(first (drop 10 (iterate (fn [[x y]] (add-and-multiply x y 2)) [(bigint 1) (bigint 2)])))
;; have a look at juxt
((juxt + * (fn [_ _ x] x)) 1 1 2) [4 2 2]
;; you can then use it like this:
(second (iterate (fn [v]
(apply (juxt + * (fn [_ _ x] x)) v)) [1 1 2])) ;; [4 2 2]
;; however it overflows quickly, so use +' *'
;; also, put it into a function
(defn add-and-multiply [times nb]
(nth (iterate (fn [v]
(apply (juxt +' *' (fn [_ _ x] x)) v)) nb) times))
(add-and-multiply 10 [1 1 2]) ;; [7983075120467448500799760620188561621081118348584N 20456985749705433596250191236583540578087736309004220218432871989995224183078912N 2]
A concise way to do this is
(defn compute [n]
(let [step (fn [[x y z :as all]] [(reduce +' all) (reduce *' all) z])]
(nth (iterate step [1 1 2]) n)))
This runs out of steam on my laptop at about n = 35.
Spelling out the computation helps a little:
(defn compute [n]
(loop [x 1, y 1, z 2, n n]
(if (zero? n)
[x y z]
(recur (+' x y z) (*' x y z) z (dec n)))))
But life is too short to wait for either of these to compute the result for n = 100.
We could pull z out of the computation either way, since it stays constant at 2. It doesn't save much to do so, so I chose to stay with the question's prescription.
When you call + with zero arguments
user=> (+)
0
I get 0 because it is invariant element to +. It works similar for *
user=> (*)
1
Why this does not work for - and / ?
user=> (-)
ArityException Wrong number of args (0) passed to: core/- clojure.lang.AFn.throwArity (AFn.java:429)
user=> (/)
ArityException Wrong number of args (0) passed to: core// clojure.lang.AFn.throwArity (AFn.java:429)
Note that - and / work differently when they are given a single argument: (- x 0) is different from (- x). The same for (/ x 1) and (/ x). The practical argument for + and * is that when your arguments may not be known beforehand, you can just apply or reduce over a list (possibly empty). The same is not true for division and negation, because you seldom need:
(apply / list)
You at least have one argument:
#(apply / (cons % list))
This is not authoritative, just a guess.
I guess the reason for this behaviour is the usage of + and * with aggregation functions: this allows to escape lots of boilerplate code in math formulas. Note the following:
(reduce + ()) => 0
(reduce * ()) => 1
the values are chosen not to affect the overall result of homogenous functions. Say you have to find the product of 10, 20, and all the items in some collection. That's what you do:
(defn product [items]
(* 10 20 (reduce * items)))
so when you have some items in a coll, it will work perfectly predictable:
(product [1 2 3]) => (* 10 20 (* 1 2 3))
and when the coll is empty you get the following:
(product []) => (* 10 20 1)
so it is exactly what you would expect.
Similar works for +
So why doesn't it work for - and / ?
i would say that they're not aggregation functions, traditionally they're opposite to aggregation. And in maths there are operators for + ( ∑ ) and * ( ∏ ), and no operators for - and /
Again, it's just a guess. Maybe there are some reasons that are much deeper.
the technical explanation would be:
if you check (source *),(source +) and (source -)
you will see that * and + can take 0 arguments while the - function will not.
(defn -
([x] (. clojure.lang.Numbers (minus x)))
([x y] (. clojure.lang.Numbers (minus x y)))
([x y & more]
(reduce1 - (- x y) more)))
I am using fungp (a genetic programming tool) to model a complex function and having trouble with sqrt.
Basically, I have to pass a vector of functions and their arity into fungp so that it can compose expressions from them. The expressions will then be evaluated and the best one will be returned. This vector of functions looks like:
(def functions
'[[+ 2]
[- 2]
[* 2]
[fungp.util/abs 1]
[fungp.util/sdiv 2]
[fungp.util/sin 1]
[fungp.util/sqrt 1]
[inc 1]
[dec 1]])
That setup gives me a hundred lines of errors like:
#<ClassCastException java.lang.ClassCastException: java.lang.Double cannot be cast to clojure.lang.IFn>
Which I believe is due to the definition of fungp.util/sqrt:
(defn sqrt [x] (if (x > 0) (Math/sqrt x) 0))
I think the 0 is causing the failure to evaluate, but I'm not sure. I've tried defining my own version of the safe square root, but couldn't get the syntax correct.
So, this is where I'm stuck. I need a version of square root that is safe (returns 0 for negative inputs) and evaluates properly in the fungp expression.
EDIT: For completeness, this is one of the (many) variations I've tried for writing my own square root wrapper:
(defn sqrt-fn [x] `(if (~x > 0) (Math/sqrt ~x) 0))
And the output (the middle bit is the expression that was generated from the functions):
#<ClassCastException java.lang.ClassCastException: clojure.lang.Cons cannot be cast to java.lang.Number>
(let [] (- (dec (- (- (fungp.util/sin (tutorial.tut1/sqrt-fn 8.0)) (fungp.util/sdiv (* x 2.0) (dec 9.0))) (fungp.util/sdiv (tutorial.tut1/sqrt-fn (* x x)) (- (- x 4.0) (+ x x))))) (fungp.util/sdiv (tutorial.tut1/sqrt-fn (fungp.util/sin (
+ (dec x) (inc x)))) (fungp.util/sdiv (* (inc (inc 1.0)) (* (+ x 9.0) (fungp.util/sin 9.0))) (tutorial.tut1/sqrt-fn (- (tutorial.tut1/sqrt-fn x) (fungp.util/abs 3.0)))))))
NullPointerException clojure.lang.Numbers.ops (Numbers.java:942)
I am not writing the expressions, so if there are extra parentheses or missing parentheses, they are coming from the way that I've defined sqrt.
There are a couple of things wrong with this:
(defn sqrt-fn [x] `(if (~x > 0) (Math/sqrt ~x) 0))
First, as hinted at in the comments, (x > 0) is trying to call x (presumably a number) as a function. > is the function, so it must come first, as in (> x 0).
Also, you probably don't want they syntax quote here - that prevents evaluation of the contents, so your function is returning a quoted list of symbols.
I'm trying to work through some of the exercises in SICP using Clojure, but am getting an error with my current method of executing Simpson's rule (ex. 1-29). Does this have to do with lazy/eager evalution? Any ideas on how to fix this? Error and code are below:
java.lang.ClassCastException: user$simpson$h__1445 cannot be cast to java.lang.Number
at clojure.lang.Numbers.divide (Numbers.java:139)
Here is the code:
(defn simpson [f a b n]
(defn h [] (/ (- b a) n))
(defn simpson-term [k]
(defn y [] (f (+ a (* k h))))
(cond
(= k 0) y
(= k n) y
(even? k) (* 2 y)
:else (* 4 y)))
(* (/ h 3)
(sum simpson-term 0 inc n)))
You define h as a function of no arguments, and then try to use it as though it were a number. I'm also not sure what you're getting at with (sum simpson-term 0 inc n); I'll just assume that sum is some magic you got from SICP and that the arguments you're passing to it are right (I vaguely recall them defining a generic sum of some kind).
The other thing is, it's almost always a terrible idea to have a def or defn nested within a defn. You probably want either let (for something temporary or local) or another top-level defn.
Bearing in mind that I haven't written a simpson function for years, and haven't inspected this one for algorithmic correctness at all, here's a sketch that is closer to the "right shape" than yours:
(defn simpson [f a b n]
(let [h (/ (- b a) n)
simpson-term (fn [k]
(let [y (f (+ a (* k h)))]
(cond
(= k 0) y
(= k n) y
(even? k) (* 2 y)
:else (* 4 y))))]
(* (/ h 3)
(sum simpson-term 0 inc n))))