I am reading Living Clojure, and this example of reduce is throwing me off.
(reduce (fn [r x]
(+ r (* x x)))
[1 2 3])
[1 2 3] is the input to reduce, along with the anonymous function.
If each member of the vector is passed in, that would only fill in r or x parameters, where does the other parameter come from?
Is there a way to step through to watch the parameters and output change?
There's a description of the first argument on ClojureDocs, but I have to admit it's not really descriptive.
The function you pass as the first argument takes two parameters, the first one is total, the second one is current. If you call reduce with only two arguments, total in first iteration is the first item of the collection, while current in first iteration is the second item of the collection. If you pass three parameters, the second one is initial value that is passed as total in the first iteration, while the first item of the collection is passed as current in first iteration:
(reduce (fn [r x] (+ r x)) 0 [1 2 3])
would iterate like this:
(+ 0 1) ;; initial value and first item of the collection
(+ (+ 0 1) 2) ;; result and second item of the collection
(+ (+ (+ 0 1) 2) 3) ;; result and third item of the collection
while without initial value
(reduce (fn [r x] (+ r x)) [1 2 3])
would iterate like this:
(+ 1 2) ;; no initial value -> first and second item of the collection
(+ (+ 1 2) 3) ;; result and third item of the collection
You could as well just add a println to see each iteration's inputs:
(reduce
(fn [r x]
(do
(println (str "r = " r ", x = " x ", (* x x) = " (* x x) ", (+ r (* x x)) = " (+ r (* x x))))
(+ r (* x x))))
[1 2 3])
the result of running it in REPL is
r = 1, x = 2, (* x x) = 4, (+ r (* x x)) = 5
r = 5, x = 3, (* x x) = 9, (+ r (* x x)) = 14
14
Related
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!
I want to write a function that inserts elements between existing elements in a vector. The inserted elements are a function of the elements that precede and succeed it, with the first and last elements remaining unaffected.
E.g. I want inserted elements to be the mean of the elements that precede and succeed it:
Input:
[1 10 15]
Output:
[1 5.5 10 12.5 15]
What is the best way to do this in Clojure?
Here's another way:
(defn insert-mean-between [xs]
(let [f (fn [x y]
[(* (+ x y) 0.5) y])]
(->> xs
(partition 2 1)
(mapcat (partial apply f))
(cons (first xs))
vec)))
(insert-mean-between [1 10 15])
;;=> [1 5.5 10 12.5 15]
The main trick is that f is returning the answer and the RHS input. This way later on they will all compose together without repeats. The only problem you will have is that the first element is missing. So we just cons it onto the front. From the outset we had to know that cons would be a convenient operation when we chose to be returning the RHS rather than the LHS.
As calculating the mean was just an example, an improved solution would be for the inserting to be independent of the mean/whatever function:
(defn calc-mean [x y] (* (+ x y) 0.5)
(insert-between calc-mean [1 10 15])
Then a more general inserting function might be:
(defn insert-between [g xs]
(->> xs
(partition 2 1)
(mapcat (fn [[x y]] [(g x y) y]))
(cons (first xs))))
and the list of variants won't be complete without the recursive lazy sequence generation:
(defn with-avg [[x1 & [x2 :as tail] :as items]]
(when (seq items)
(if (seq tail)
(lazy-cat [x1 (/ (+ x1 x2) 2)] (with-avg tail))
[x1])))
user> (with-avg [1 2 3 4 5])
;;=> (1 3/2 2 5/2 3 7/2 4 9/2 5)
user> (with-avg [1])
;;=> [1]
user> (with-avg [])
;;=> nil
user> (with-avg [1 2])
;;=> (1 3/2 2)
user> (with-avg [1 2 3])
;;=>(1 3/2 2 5/2 3)
One way I could solve it is pattern matching Vector as f s t, I'm assuming it has 3 elements
Then create variable to assign first median first + second / 2 and second median second + third /2.
At the end return a new Vector with a combination you want.
Example, (I'm using lein REPL)
user=> (defn insert_medians[vect]
#_=> (let [[f s t] vect
#_=> m1 (float (/ (+ f s) 2))
#_=> m2 (float (/ (+ s t) 2))]
#_=> [f m1 s m2 t]))
#'user/insert_medians
user=> (insert_medians [1 10 15])
[1 5.5 10 12.5 15]
If a vector is larger than 3 elems, you need to find all the medians first and then insert into the original vector using interleave fn.
(defn insert-between
"Inserts elements between existing elements in a vector v. The inserted
elements are a result of applying the function f to the elements that precede
and succeed it, with the first and last elements of v remaining unaffected."
[f [x & xs :as v]]
(->> (partition 2 1 v)
(mapcat (fn [[a b]] [(f a b) b]))
(cons x)
(into [])))
(defn mean [& numbers]
(float (/ (apply + numbers) (count numbers))))
(insert-between mean [1 10 15]) ; => [1 5.5 10 10 12.5 15]
(insert-between + [1 10 15 20 25]) ; => [1 11 10 25 15 35 20 45 25]
(insert-between mean []) ; => [nil] :(
I am stuck at the Pascal's Trapezoid from 4Clojure site, where you need to build a lazy sequence of the trapezoid's numbers.
My first shot was this:
(defn pascal [x]
(cons x
(lazy-seq
(pascal
(map +
(cons 0 x)
(conj x 0)
)))))
Which didn't work:
user=> (take 5 (pascal [1 1]))
([1 1] (1 2 1) (0 2 4 2) (0 0 4 8 4) (0 0 0 8 16 8))
Writing it this way works, however:
(defn pascal2 [x]
(cons x
(lazy-seq
(pascal2
(map +
(concat [0] x)
(concat x [0])
)))))
user=> (take 5 (pascal2 [1 1]))
([1 1] (1 2 1) (1 3 3 1) (1 4 6 4 1) (1 5 10 10 5 1))
So, what exactly am I doing wrong here? What is the difference between cons/conj and concat?
As others stated conj inserts the element(s) it receives in a different position depending on the concrete collection type, see this SO question for more detailed information about the difference between conj and cons.
In the first version of your pascal function you are providing a vector as the initial argument so the expression (conj x 0) will insert the 0 at the end of the vector for the computation of the second element in the series, but since map returns a lazy sequence, when the third element is computed the insertion happens at the beginning ((conj (map inc '(0)) 2) ;= (2 1)), which results in wrong elements in the series from then on.
In order to use the cons and conj approach you have to make sure you return a vector by using mapv instead of map.
(defn pascal [x]
(cons x
(lazy-seq
(pascal
(mapv +
(cons 0 x)
(conj x 0))))))
(take 5 (pascal [1 1]))
;= ([1 1] [1 2 1] [1 3 3 1] [1 4 6 4 1] [1 5 10 10 5 1])
The drawback with mapv is that it is eager so it will compute all members in the pascal element, instead of just holding it back until you actually need them.
On the other hand, when using concat you do ensure you append the element at the end and that everything is lazy, but the append is not done cheaply like with vectors, see here for more information.
Regardless of these factors you can still use cons in both cases, since what it does is what you need in either case (i.e. have an element inserted at the beginning of a collection).
(defn pascal2 [x]
(cons x
(lazy-seq
(pascal2
(map +
(cons 0 x) ; Replaced concat with cons
(concat x [0]))))))
(take 5 (pascal2 [1 1]))
;= ([1 1] (1 2 1) (1 3 3 1) (1 4 6 4 1) (1 5 10 10 5 1))
According to ClojureDocs
conj
conj clojure.core
(conj coll x)
(conj coll x & xs)
conj[oin]. Returns a new collection with the xs 'added'. (conj nil
item) returns (item). The 'addition' may happen at different 'places'
depending on the concrete type.
conj accepts the first argument as a collection, which means coll must be a collection type. conj will return a new collection with x added into coll, and the place of x added is depending on the type of coll.
e.g.
> (conj [1] [0])
[1 [0]] ; See [0] is added into [1] as an element. Instead of returning [1 0], it returns [1 [0]]
> (conj [1] 0)
[1 0]
> (conj '(1) 0)
(0 1) ;See the element `0` position is different in each case.
concat
concat clojure.core
(concat)
(concat x)
(concat x y)
(concat x y & zs)
Returns a lazy seq representing the concatenation of the elements in
the supplied colls.
concat accepts all the argument as collection types, which is different from conj. concat returns the concatenation of arguments.
e.g.
> (concat [0] [1])
(0 1)
> (concat [0] [[1]])
(0 [1])
> (concat [0] 1) ;See the second argument is not a collection type, thus the function throws an exception.
java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long
>
cons
cons clojure.core
(cons x seq)
Returns a new seq where x is the first element and seq is the rest.
The doc of cons states clearly how cons would work. The second argument of cons must be a seq.
e.g.
> (cons [1] [0])
([1] 0) ; [1] is the first element and (0) is the rest
> (first (cons [1] [0]))
[1]
> (rest (cons [1] [0]))
(0)
> (cons 1 [0]) ; 1 is the first element and (0) is the rest
(1 0)
> (cons [1] 0) ;the second argument is not a seq, throwing exception
java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long
conj on a list adds the element to the front of the list.
If you convert the list to a vector it will work.
user=> (conj '(1 2 3) 4)
(4 1 2 3)
user=> (conj [1 2 3] 4)
[1 2 3 4]
Suppose you have three functions of arity 1, 2 and 3 as below:
(defn I [x] x)
(defn K [x y] x)
(defn S [x y z] (x z (y z)))
Does clojure have an evaluation function or idiom for evaluating:
(I K S I I) as (I (K (S (I (I)))))
returning a parital function of arity 2?
I am considering creating a macro that can take the simple function definitions above and expand them to multi-arity functions that can return partial results. I would not want to create the macro if there is already a built in or idiomatic way to accomplish this.
Here is what the expanded macros would like for the above functions:
(defn I
([x] I x)
([x & more] (apply (I x) more)))
(defn K
([x] (partial K x))
([x y] x)
([x y & more] (apply (K x y) more)))
(defn S
([x] (partial S x))
([x y] (partial S x y))
([x y z] (x z (y z)))
([x y z & more] (apply (S x y z) more)))
I'm not sure I fully understand what you are trying to do, but the comp function is useful for doing this kind of "function chaining" you seem to be talking about. For example:
user> ((comp vec rest list) 1 2 3 4 5)
=> [2 3 4 5]
Which is equivalent to:
user> (vec (rest (list 1 2 3 4 5)))
=> [2 3 4 5]
In your case, if you have the list (I K S I I), and you want to evaluate it as (I (K (S (I (I))))), I would use (reduce comp ...), but you could also use (apply comp ...).
user> ((reduce comp [vec rest list]) 1 2 3 4 5)
=> [2 3 4 5]
user> ((apply comp [vec rest list]) 1 2 3 4 5)
=> [2 3 4 5]
You may also be interested in the -> or ->> macros. These macros nest their arguments sequentially into the next arguments. The -> macro will nest into the first position of the next expression, whereas the ->> macro will nest into the last position of the next expression. If the "next thing" is a function, both will behave the same, and form an expression of (function nested-things-so-far), and continue along.
Really, examples are best:
(-> 1 (+ 10) (- 100) inc)
;//Expands to...
(inc (- (+ 1 10) 100))
;//Evaluating in the REPL...
user> (-> 1 (+ 10) (- 100) inc)
=> -88
(->> 1 (+ 10) (- 100) inc)
;//Expands to...
(inc (- 100 (+ 10 1)))
;//Evaluating in the REPL...
user> (-> 1 (+ 10) (- 100) inc)
=> 90
However, it seems more like you want to do something involving auto-currying (although, again, I don't think I fully understand), and for that I don't know of anything pre-existing built-in way.
The clojure document gives the following examples:
(take 10 (iterate (partial + 2) 0))
(def powers-of-two (iterate (partial * 2) 1))
(take 10 powers-of-two)
(def fib (map first (iterate (fn [[a b]] [b (+ a b)]) [1 1])))
(take 10 fib)
Anyone can explain the syntax of clojure's iterate function in more detail? I am very confused with all the usage. Why two brackets are there in (fn [[a b]] [b (+ a b)])?
Another example can be found here:
(defn iter [[x y]]
(vector y (+ x y)))
(nth (iterate iter [0 1]) 10000)
iterate takes a function f and an initial value x and produces a lazy sequence. The first element in the seq is x. Each subsequent element is computed by calling f with the previous element.
Example 1:
(iterate (partial + 2) 0)
This generates a sequence, starting at 0, where each element is the previous element with 2 added to it. I.e.:
0
(+ 2 0) ; => 2
(+ 2 2) ; => 4
(+ 2 4) ; => 6
; etc
Each element in the seq is passed to (partial + 2) when generating the following element.
Example 2:
(iterate (partial * 2) 1)
This generates a sequence, starting at 1, where each element is the previous element multiplied by 2. I.e.:
1
(* 2 1) ; => 2
(* 2 2) ; => 4
(* 2 4) ; => 8
(* 2 8) ; => 16
; etc
Again, you can see how each element feeds into the generation of the next one.
Example 3:
(iterate (fn [[a b]] [b (+ a b)]) [1 1])
Firstly, (fn [[a b]] ...) is a way to destructure a value into parts. In this case, the function accepts a two-element vector and unpacks it into the local variables a and b.
The function returns a two-element vector containing b and the sum of a and b (i.e. the second value in the previous pair and the sum of both values in the previous pair).
With this in mind, this iterate call generates:
[1 1]
[1 (+ 1 1)] ; => [1 2]
[2 (+ 1 2)] ; => [2 3]
[3 (+ 2 3)] ; => [3 5]
[5 (+ 3 5)] ; => [5 8]
; etc
Then (map first ...) grabs the first value in each pair, which gives you your Fibonacci sequence.