ArityException Wrong number of args (0) passed to: core/max - clojure

If I run this code, I will get an error "ArityException Wrong number of args (0) passed to: core/max"
(apply max (filter #(zero? (mod % 7)) (range 1 3)))
However, if I run this code
(apply max (filter #(zero? (mod % 7)) (range 1 10)))
then I get the result 7.
Is there anyone who can help me to figure out this problem?

(filter #(zero? (mod % 7)) (range 1 3))
this, produces an empty sequence.
However, max must be called with at least one argument. When you apply an empty sequence to it, it's called with zero arguments, and this produces the arity exception.
You could do something like this:
(defn my [a b]
(let [result (filter #(zero? (mod % 7)) (range a b))]
(if (zero? (count result))
nil ; or 0 or.. whatever
(apply max result))))
apply and reduce
Because the question came up, here's a short explanation of the difference between apply and reduce.
They are two totally different concepts, however, in the following case both do the same job when combined with max.
let xs be any collection of numbers.
(apply max xs) equals (reduce max xs)
apply
Usually functions are called with a number of arguments, so one can call max like so: (max 3), or (max 5 9), or (max 4 1 3) ... As noticed before: just (max) would be an arity exception.
Apply however, lets someone call a function passing the arguments in the form of a collection. So in correspondence to the last example, the following is possible: (apply max [3]), or (apply max [5 9]), or (apply max [4 1 3]) ... Just (apply max []) or even (apply max) would lead to the same arity exception as above. This is useful in many cases.
reduce
Reduce in contrast is a bit trickier. Along with map and filter it's absolutely essential for functional programming languages like Clojure.
The main idea of reduce is to walk through a collection, in each step desired information from the current item is processed and added to a memo or accumulator.
Say, one wants to find out the sum of all numbers in a collection.
Let xs be [3 4 5 23 9 4].
(reduce + xs) would do the job.
more explicitly one could write: (reduce (fn [memo value] (+ memo value)) xs)
The function which is passed as the first argument to reduce expects two parameters: The first one is the memo, the second one the value of the current item in the collection. The function is now called for each item in the collection. The return value of the function is saved as the memo.
Note: that the first value of the collection is used as an initial value of the memo, hence the iteration starts with the second value of the collection. Here's what it is doing:
(+ 3 4) ; memo is 7 now
(+ 7 5) ; memo is 12 now
(+ 12 23) ; memo is 35 now
(+ 35 9) ; memo is 44 now
(+ 44 4) ; memo is 48 now
(There's also a way to specify the start value of the memo, see clojuredocs.org for more details)
This works equally with max. In each iteration the value of the current item is compared with the memo. Each time the highest value is saved to the memo: Hence the memo in this case represents the "maximum value until now".
So (reduce max [4 1 3 5 2]) is calculated like this:
(max 4 1) ; memo is 4
(max 4 3) ; memo is 4
(max 4 5) ; memo is 5
(max 5 2) ; memo is 5
so?
Which one to use now? It showed that there's not really a notable difference in the time that (reduce max (range 100000000)) and (apply max (range 100000000)) take. Anyways, the apply solution looks easier to me, but that's just my opinion.

There are no numbers divisible by 7 between 1 and 3, the result of filter in your first example returns an empty sequence, which means that the first example if calling (apply max []) which is the same as calling (max). max requires at least one parameter, hence the ArityException.
A couple of options to fix it:
(last (filter #(zero? (mod % 7)) (range 1 3))
or
(if-let [by-7 (seq (filter #(zero? (mod % 7)) (range 1 3)))]
(apply max by-7)
nil ;; or whatever value in case the collection is empty
)

According to the error message, the number of arguments that are passed to max is 0, and that is wrong. I guess it makes sense because it's impossible to compute the maximum for an empty list.
The reason why max gets no arguments is that there are no numbers divisible by 7 between 1 and 3.

Related

Using partial over a collection, reduce -vs- apply

I have this curious demonstration of partials. Here is the code:
Start by declaring a vector and a partial. As expected, reduce and apply sums the integers on vector a:
> (def a [1 2 3 4 5])
> (def p (partial + 10))
> (apply + a)
15
> (reduce + a)
15
Now, using apply on the partial p and vector a, I'm getting the sum of a and the +10 from the partial, which makes sense:
> (apply p a)
25
Now, using (reduce) makes no sense to me. Where is 55 coming from?
> (reduce p a)
55
The closest I can come up with is, (reduce) version is adding 10 from the 1 index and ignoring the zero index before adding everything together:
> (+ (first a) (reduce + (map #(+ % 10) (rest a))))
55
I'm just curious if anyone knows what is happening here, exactly? I don't really know what answer I'm expecting with this, but I also don't understand what is happening either. I have no idea why I would get 55 as an answer.
The first thing to note is that + is variadic: it can be called with zero, one, two, or more arguments. When you do (apply + a) you are essentially calling + with five arguments and getting the sum back (15).
However, reduce treats the function as strictly binary and calls it repeatedly, with the result of the previous call as the first argument of the next call. (reduce + a) is (+ (+ (+ (+ 1 2) 3) 4) 5) which also happens to be 15.
So your partial is also variadic and can be called with five arguments, as in the apply call: (apply p a) = (p 1 2 3 4 5) = (+ 10 1 2 3 4 5) so you get 25.
The reduce on p is going to call it repeatedly as shown above, but this time the function adds 10 in each time: (reduce p a) = (p (p (p (p 1 2) 3) 4) 5) = (+ 10 (+ 10 (+ 10 (+ 10 1 2) 3) 4) 5) so you get four 10s and the 15 making 55.
Another way of looking at Sean Corfield's fine answer:
Given
(def p (partial + 10))
then (p x y) means (+ 10 x y), for any x and y.
So
(reduce p a)
means
(reduce (fn [x y] (+ 10 x y)) a)
... since the first argument to reduce is a function of two arguments.
No initial value is supplied, so (first a) is used as such, and the reduction is applied to (rest a), which has four elements.
All the elements of a get added in: the first as the initial value;
the others by reduction.
The 10 gets added on in every cycle of the reduction: four times.
So the final result is the same as
(+ (* 10 (dec (count a))) (reduce + a))
In this case, 55.

How to properly bind greater and lesser values in the loop in Clojure?

I need to bind properly the greater and lesser value in the initial binding in the loop. The values are provided in ad-hoc order, so I need to distinguish them first. The loop itself is used inside an anonymous function.
So, I need to do something like:
(#(loop [divident %1 divisor %2] (some-recursion)) greater lesser)
or, this in case of swapped arguments:
(#(loop [divident %2 divisor %1] (some-recursion)) lesser greater)
If you need values to be in order from greater to lesser or lesser to greater then you could use the functions sort and sort-by. For instance:
(sort [1 7 4 6])
;;=> (1 4 6 7)
(sort-by - [1 7 4 6])
;;=> (7 6 4 1)
So for two numbers you can easily destructure the sort result:
(let [[lesser greater] (sort [7 1])]
(println lesser greater))
;;=> 1 7
Applying that to the loop:
(defn x-1 []
(#(let [[lesser greater] (sort [%1 %2])]
(loop [bigger greater
smaller lesser]
(println smaller bigger))) 7 1))
;;=> 1 7
For two numbers, the simplest approach is just to use max and min in the loop binding:
(#(loop [dividend (max %2 %1)
divisor (min %2 %1)]
(println (format "larger: %d smaller: %d" dividend divisor)))
2 1)
Not sure that this is a proper solution, but: we can do any initial binding and than do the appropriate binding switch in the first recursion loop.
Here is an example of implementation of the Euclidean algorithm as an anonymous function:
(#(loop [dd %1 dr %2]
(if (zero? (rem dd dr))
dr
(recur dr (rem dd dr))))
858 1023)
;; -> 33
(#(loop [dd %1 dr %2]
(if (zero? (rem dd dr))
dr
(recur dr (rem dd dr))))
1023 858)
;; -> 33

Append to clojure vector from within loop

I have:
(defn keep?
(def sum [])
(loop [i 0]
(when (< i 10)
(conj sum 10)
(recur (inc i))))
sum
)
This just gives me and empty vector even though I am conj-ing 10 onto sum. Is this because it is not in-scope within the Loop? How would I achieve the same outcome. (btw, this example is deliberately simplified)
Thanks
conj does not modify its argument. In fact, without resorting to evil reflection tricks, nothing will modify a vector, it's an immutable data structure. This is one of the fundamental principles of Clojure.
In functional programming, instead of modifying data, we replace it with another immutable value. So you need to use the return value of conj, or it is effectively a noop.
(defn keep?
[]
(loop [i 0 sum []]
(if (< i 10)
(recur (inc i) (conj sum 10))
sum)))
Also, the second arg to defn must always be a vector.
conj is not destructive, it does not alter that collection, returns a new collection with the designated state (reference).
To achieve the desired result, you may:
Define sum in a loop-form, like i is defined, instead of using def
recur (inc i) (conj sum 10) to rebind sum to a new one on every iteration, so that state is built up to what you expect
Once the condition in when is not met, just return sum from your loop and it will bubble up to become the return value of this function. Uh hang on, when does not have an "else-branch", a possible alternative is if
Like so:
(defn keep? []
(loop [i 0
sum []]
(if (< i 10)
(recur (inc i)
(conj sum 10))
sum)))
Just to supplement the other answers, I almost never use the loop function. Here are a few ways to do it using the for function:
; return a lazy sequence
(for [i (range 10) ]
i)
;=> (0 1 2 3 4 5 6 7 8 9)
; return a concrete vector
(vec
(for [i (range 10) ]
i))
;=> [0 1 2 3 4 5 6 7 8 9]
; 'into' is very nice for converting one collection into another
(into #{}
(for [i (range 10) ]
i))
;=> #{0 7 1 4 6 3 2 9 5 8} ; hash-set is unique but unordered

find all subsets of an integer collection that sums to n

i'm trying to find a function that, given S a set of integer and I an integer, return all the subsets of S that sum to I
is there such a function somewhere in clojure-contrib or in another library ?
if no, could anyone please give me some hints to write it the clojure way?
Isn't this the subset sum problem, a classic NP-complete problem?
In which case, I'd just generate every possible distinct subset of S, and see which subsets sums to I.
I think it is the subset sum problem, as #MrBones suggests. Here's a brute force attempt using https://github.com/clojure/math.combinatorics (lein: [org.clojure/math.combinatorics "0.0.7"]):
(require '[clojure.math.combinatorics :as c])
(defn subset-sum [s n]
"Return all the subsets of s that sum to n."
(->> (c/subsets s)
(filter #(pos? (count %))) ; ignore empty set since (+) == 0
(filter #(= n (apply + %)))))
(def s #{1 2 45 -3 0 14 25 3 7 15})
(subset-sum s 13)
; ((1 -3 15) (2 -3 14) (0 1 -3 15) (0 2 -3 14) (1 2 3 7) (0 1 2 3 7))
(subset-sum s 0)
; ((0) (-3 3) (0 -3 3) (1 2 -3) (0 1 2 -3))
These "subsets" are just lists. Could convert back to sets, but I didn't bother.
You can generate the subsets of a set like this:
(defn subsets [s]
(if (seq s)
(let [f (first s), srs (subsets (disj s f))]
(concat srs (map #(conj % f) srs)))
(list #{})))
The idea is to choose an element from the set s: the first, f, will do. Then we recursively find the subsets of everything else, srs. srs comprises all the subsets without f. By adding f to each of them, we get all the subsets with f. And together, that's the lot. Finally, if we can't choose an element because there aren't any, the only subset is the empty one.
All that remains to do is to filter out from all the subsets the ones that sum to n. A function to test this is
(fn [s] (= n (reduce + s)))
It is not worth naming.
Putting this together, the function we want is
(defn subsets-summing-to [s n]
(filter
(fn [xs] (= n (reduce + xs)))
(subsets s)))
Notes
Since the answer is a sequence of sets, we can make it lazier by changing concat into lazy-cat. map is lazy anyway.
We may appear to be generating a lot of sets, but remember that they share storage: the space cost of keeping another set differing by a single element is (almost) constant.
The empty set sums to zero in Clojure arithmetic.

repeatedly apply a function until test no longer yields true

I wrote this code to nest a function n times and am trying to extend the code to handle a test. Once the test returns nil the loop is stopped. The output be a vector containing elements that tested true. Is it simplest to add a while loop in this case? Here is a sample of what I've written:
(defn nester [a inter f]
(loop [level inter expr a]
(if (= level 0) expr
(if (> level 0) (recur (dec level) (f expr))))))
An example input would be an integer 2, and I want to nest the inc function until the output is great than 6. The output should be [2 3 4 5 6 7].
(defn nester [a inter f test-fn]
(loop [level inter
expr a]
(if (or (zero? level)
(nil? (test-fn expr)))
expr
(recur (dec level)
(f expr)))))
If you also accept false (additionally to nil) from your test-fn, you could compose this more lazily:
(defn nester [a inter f test-fn]
(->> (iterate f a)
(take (inc inter))
(drop-while test-fn)
first))
EDIT: The above was answered to your initial question. Now that you have specified completely changed the meaning of your question:
If you want to generate a vector of all iterations of a function f over a value n with a predicate p:
(defn nester [f n p]
(->> (iterate f n)
(take-while p)
vec))
(nester inc 2 (partial > 8)) ;; predicate "until the output is greater than six"
;; translated to "as long as 8 is greater than
;; the output"
=> [2 3 4 5 6 7]
To "nest" or iterate a function over a value, Clojure has the iterate function. For example, (iterate inc 2) can be thought of as an infinite lazy list [2, (inc 2), (inc (inc 2)), (inc (inc (inc 2))) ...] (I use the [] brackets not to denote a "list"--in fact, they represent a "vector" in Clojure terms--but to avoid confusion with () which can denote a data list or an s-expression that is supposed to be a function call--iterate does not return a vector). Of course, you probably don't want an infinite list, which is where the lazy part comes in. A lazy list will only give you what you ask it for. So if you ask for the first ten elements, that's what you get:
user> (take 10 (iterate inc 2))
> (2 3 4 5 6 7 8 9 10 11)
Of course, you could try to ask for the whole list, but be prepared to either restart your REPL, or dispatch in a separate thread, because this call will never end:
user> (iterate inc 2)
> (2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
=== Shutting down REPL ===
=== Starting new REPL at C:\Users\Omnomnomri\Clojure\user ===
Clojure 1.5.0
user>
Here, I'm using clooj, and this is what it looks like when I restart my REPL. Anyways, that's all just a tangent. The point is that iterate answers the core of your question. The other part, stopping upon some test condition, involves take-while. As you might imagine, take-while is a lot like take, only instead of stopping after some number of elements, it stops upon some test condition (or in Clojure parlance, a predicate):
user> (take-while #(< % 10) (iterate inc 2))
> (2 3 4 5 6 7 8 9)
Note that take-while is exclusive with its predicate test, so that here once the value fails the test (of being less than 10), it excludes that value, and only includes the previous values in the return result. At this point, solving your example is pretty straightfoward:
user> (take-while #(< % 7) (iterate inc 2))
> (2 3 4 5 6)
And if you need it to be a vector, wrap the whole thing in a call to vec:
user> (vec (take-while #(< % 7) (iterate inc 2)))
> [2 3 4 5 6]