Using partial over a collection, reduce -vs- apply - clojure

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.

Related

Creating a sequence of all values in Clojure

I'm currently working on a kata code challenge and it comes with a few requirements:
The number u(0) = 1 is the first one in u.
For each x in u, then y = 2 * x + 1 and z = 3 * x + 1 must be in u too.
There are no other numbers in u.
I have constructed a few functions:
(defn test2 [x n orgN] ;;x is a counter, n is what I want returned as a list
(println n)
(println "this is x: " x)
(cons n (if (not= x (- orgN 1 ))
(do (test2 (+ x 1) (+ 1 (* n 2)) orgN)
(test2 (+ x 1) (+ 1 (* n 3)) orgN))
nil)
))
(defn test2helper [n]
(def x 1)
(test2 x x n)
)
(test2helper 5)
However this only returns (1 4 13 40) and misses a whole bunch of values in between. Cons is only constructing a list based on the last 3n+1 algorithm and not picking up any other values when I want instead a sequence of the two values generated from each n value repeated. My question is is there a way to construct a sequence of all the values instead of just 4 of them?
https://www.codewars.com/kata/twice-linear/train/clojure
This solution is pretty close to being correct. But remember that do is for performing side effects, not for producing values. Specifically, (do x y) returns y after performing the side effects in x. But test2 does not have any side effects: it just returns a list. What you are looking for is instead (concat x y), a function which concatenates two lists together into a larger list.
Although Alan Malloy's solution answers your question, it does not solve the problem you refer to, which requires that the sequence is generated in increasing order.
My approach would be to generate the sequence lazily, according to the following pattern:
(defn recurrence [f inits]
(map first (iterate f inits)))
For example, you can define the Fibonacci sequence like this:
(defn fibonacci []
(recurrence (fn [[a b]] [b (+ a b)]) [1 1]))
=> (take 10 (fibonacci))
(1 1 2 3 5 8 13 21 34 55)
The sequence you need is harder to generate. Good hunting!

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

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.

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

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]

Processing a seq by accessing its prior elements

I want to create a sequence, however to create its every element I need access to the two previous elements. What is the generic way to do such things in clojure ?
So two slightly diff cases -
a) seq is (a b c) when I am processing c I want to have access to a and b ....
b) and having such ability to create the sequence itself by always being able to access th two previous elements.
Thanks,
Murtaza
partition gives you this nearly for free:
(partition-all 3 1 (range 100))
((0 1 2) (1 2 3) (2 3 4) (3 4 5) (4 5 6) (5 6 7) (6 7 8) ... )
then you can map your function over the sequence of partitions:
(map my-func (partition-all 3 1 (range 100)))
you just need to make your function aware of the fact that the last segment may have less than three elements if your seq is not a multiple of three. if you want to just drop any extras use partition instead of partition-all
Well, here is one way to do it. Assume you have a function g that takes the last two values as input and produces the next value.
(defn f [g x0 x1]
(let [s (g x0 x1)]
[s (fn [] (f g x1 s))]))
Given g and two consecutive values in the sequence, f returns a pair consisting of the next value and a function that will return the value after that. You can use f as follows to generate an infinite sequence of such pairs:
(iterate (fn [[v h]] (h)) (f g x0 x1))
To extract just the sequence values, do this:
(map first (iterate (fn [[v h]] (h)) (f g x0 x1)))
For example:
user=> (take 10 (map first (iterate (fn [[v h]] (h)) (f + 0 1))))
(1 2 3 5 8 13 21 34 55 89)
You can iterate using a vector of two elements and then take the first of the resulting sequence.
For example, to create the fibonacci series:
user=> (def fib (map first (iterate (fn [[a b]] [b (+ a b)]) [1 1])))
#'user/fib
user=> (take 10 fib)
(1 1 2 3 5 8 13 21 34 55)