Unexpected result from reduce function - clojure

I would like to get the smallest element from a vector. For this I use combine the reduce and min functions. However, when providing my own implementation of min I get unexpected results:
user=> (reduce (fn [x y] (< x y) x y) [1 2 3 2 1 0 1 2])
2
user=> (reduce min [1 2 3 2 1 0 1 2 3])
0
The reduce with standard min returns 0 as expected. However, when I provide my own implementation it returns 2. What am I doing wrong?

You're missing an if:
(reduce (fn [x y] (if (< x y) x y)) ...)
^-- note the if
works fine. :-)

You are missing if around the function's body. What happens now is:
user> (use 'clojure.contrib.trace)
nil
user> (defn foo [x y] (< x y) x y)
#'user/foo
user> (dotrace [foo] (reduce foo [1 2 3 2 1 0 1 2]))
TRACE t2229: (foo 1 2)
TRACE t2229: => 2
TRACE t2230: (foo 2 3)
TRACE t2230: => 3
TRACE t2231: (foo 3 2)
TRACE t2231: => 2
TRACE t2232: (foo 2 1)
TRACE t2232: => 1
TRACE t2233: (foo 1 0)
TRACE t2233: => 0
TRACE t2234: (foo 0 1)
TRACE t2234: => 1
TRACE t2235: (foo 1 2)
TRACE t2235: => 2
2
In other words the function you pass in always returns y, so in the last iteration 2 is returned, since 2 is the last number of the sequence you reduced.
Also note that min already is based on reduce:
(defn min
"Returns the least of the nums."
([x] x)
([x y] (if (< x y) x y))
([x y & more]
(reduce min (min x y) more)))

A fn used with reduce probably needs to handle 3 arities - 0, 1, and 2 arguments.

Related

Clojure Fibonacci series using while in atom

How to achieve this using Clojure atom on the Fibonacci series.
(def x 0)
(def y 0)
(def z 1)
(defn problem []
(def a (atom 0))
(while (< #a 10 )
(do
;logic code need to write to achieve the output
; how can I add b,c == c,b???????.)
(swap! a inc)))
(problem)
output should be 0 1 1 2 3 5 8 13 21 34 55
As mentioned in the comments, defining and using an atom in a function is a totally non-clojure way of solving the question which makes it all the more difficult to solve. You should get familiar with the concept of immutability and higher order functions like map, filter, reduce, etc.
The code below gives you what you want.
(def fib1
(fn [n]
(cond
(= n 0) 1
(= n 1) 1
:else (+ (fib1 (dec n)) (fib1 (- n 2))))))
since this gives you just nth Fibonacci number, you should take + map with it if you want to get what you want.
(take 10 (map fib1 (range))) => (1 1 2 3 5 8 13 21 34 55)
take a look at this beautiful solution I found on internet.
(def fib-seq-iterate (map first (iterate (fn [[n m]] [m (+ n m)]) [0 1])))
This returns a lazy sequence, which can be called with
(take 5 fib-seq-iterate) => (0 1 1 2 3)
(def x 0)
(def y 0)
(def z 1)
(defn problem []
(def a (atom 0))
(while (< #a 10 )
(do
(println x)
(def x (+ y z))
(def y z)
(def z x)
(swap! a inc))))
(problem)
Output:
0 1 2 3 5 8 13 21 34 55

Convert list of lists into string in Clojure

How do I convert a LazySeq which is a list of lists into a string that has the exact same structure and parantheses?
(def my-list (lazy-seq '((a b 0 1 x y) (a b 0 4 x y) (a b 0 3 x y) )))
(def string-list (print-to-string my-list ))
string-list
;; should return "((a b 0 1 x y) (a b 0 4 x y) (a b 0 3 x y) ))"
;; but returns "clojure.lang.LazySeq#72251662"
If you want to keep the data as they are (or at least do your best with it), don't use str, but use pr-str. It might make no difference for simple things, but it will for more complex data structures.
E.g
user=> (pr-str (lazy-seq '((a b 0 1 x y) (a b 0 4 x y) (a b 0 3 x y) )))
"((a b 0 1 x y) (a b 0 4 x y) (a b 0 3 x y))"
for lazy sequences you can use print-str, which is alike simple print but writes the result to string.
user> (print-str my-list)
;;=> "((a b 0 1 x y) (a b 0 4 x y) (a b 0 3 x y))"
but beware, it obviously realizes the collection, and in case of infinite seq it would hang forever.
also you can override the print behaviour for any data type you want:
(defmethod print-method clojure.lang.LazySeq [data ^java.io.Writer w]
(let [[firsts] (split-at 10 data)]
(if (= 10 (count firsts))
(.write w (str (seq firsts) " :: more"))
(.write w (str (seq firsts))))))
user> (print-str (lazy-seq (range 1000)))
;;=> "(0 1 2 3 4 5 6 7 8 9) :: more"

Whats the difference between (concat [x] y) and (cons x y)?

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]

How to (elegantly) iterate two lists at once?

I want to find better looking alternative to this code:
(def x (range 1 10))
(def y '(0 4 3 5 1 2 7 3 11))
(for [i (range 0 (count y))] [(nth x i) (nth y i)])
If I already have the result of previous I can simply
(def z (for [i (range 0 (count y))] [(nth x i) (nth y i)]))
(for [[x y] z] [x y])
Can you find some better looking alternative?
Example is made to be short and easilly to read. If you modify it to do something more complicated the first example can stop being readable.
You can use map:
(map vector x y)

Can clojure evaluate a chain of mixed arity functions and return a partial function if needed?

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.