New to Clojure so I've been going through 4Clojure's questions to get familiar with the core library before jumping on a project and have ran into this question:
// Write a function which reverses a sequence.
(= (__ [1 2 3 4 5]) [5 4 3 2 1])
This is just one of the test-cases but here is what I had come up with:
(fn [x my-seq]
(if (empty? my-seq)
x
(do
(into x (take-last 1 my-seq))
(recur x (into [] (drop-last my-seq)))))) []
I was getting an empty vector [ ] after executing this code in a repl so
I modified the code like so:
(fn [x my-seq]
(if (empty? my-seq)
x
(recur (into x (take-last 1 my-seq)) (into [] (drop-last my-seq))))) []
Question is why was my previous code not working? To me it seems logically equivalent, the modified code just seems cleaner where it avoids the do form. Again I'm new to Clojure so i'm not entirely familiar with the do and recur forms.
(into x (take-last 1 my-seq)) is the problem.
Note that you cannot change x. (into x ...) creates a new vector and returns it.
However the return values of every statement inside (do ...) except for the last one are dropped. You are recurring with the original - empty - x.
Related
I am trying to understand the below program to find the Fibonacci series using recursion in Clojure.
(defn fib
[x]
(loop [i '(1 0)]
(println i)
(if (= x (count i))
(reverse i)
(recur
(conj i (apply + (take 2 i))))))) // This line is not clear
For ex for a call fib(4) I get the below output,
(1 0)
(1 1 0)
(2 1 1 0)
(0 1 1 2)
Which as per my inference the conj seems to add the value of (apply + (take 2 i)) to the start of the i. But that is not the behaviour of conj. Can someone help me understand how exactly this works?
That is the behavior of conj, for lists. conj doesn't always add to the end:
(conj '(1) 2) ; '(2 1)
(conj [1] 2) ; [1 2]
The placement of the added element depends on the type of the collection. Since adding to the end of a list is expensive, conj adds to to front instead. It's the same operation (adding to a list), but optimized for the collection being used.
Per Clojure documentation:
The 'addition' may happen at different 'places' depending on the concrete type.
Appending to list happens to beginning of list, appending to vector happens to the end...
See more examples at https://clojuredocs.org/clojure.core/conj
I'm looking for a way how to use map function in more custom way. If there is a different function for what I'm trying to achieve, could you please let me know this.
;lets say i have addOneToEach function working as bellow
(defn plusOne[singleInt]
(+ 1 singleInt))
(defn addOneToEach[intCollection] ;[1 2 3 4]
(map plusOne intCollection)) ;=>(2 3 4 5)
;But in a case I would want to customly define how much to add
(defn plusX[singleInt x]
(+ x singleInt))
(defn addXToEach[intCollection x] ;[1 2 3 4]
;how do I use plusX here inside map function?
(map (plusX ?x?) intCollection)) ;=>((+ 1 x) (+ 2 x) (+ 3 x) (+ 4 x))
I'm not looking for a function that adds x to each in the collection, but a way to pass extra arguments to the function that map is using.
another option to the already mentioned would be partial (note that in the example the order of the params does not matter, since you just add them, but partial binds them from left to right, so beware):
user=> (doc partial)
-------------------------
clojure.core/partial
([f] [f arg1] [f arg1 arg2] [f arg1 arg2 arg3] [f arg1 arg2 arg3 & more])
Takes a function f and fewer than the normal arguments to f, and
returns a fn that takes a variable number of additional args. When
called, the returned function calls f with args + additional args.
nil
user=> (defn plus-x [x i] (+ x i))
#'user/plus-x
user=> (map (partial plus-x 5) [1 2 3])
(6 7 8)
There are several ways to go about it. One is using an explicit local function via letfn:
(defn add-x-to-each [ints x]
(letfn [(plus-x [i]
(+ i x))]
(map plus-x ints)))
For this small piece of code this is probably overkill and you can simply streamline it via an anonymous function:
(defn add-x-to-each [ints x]
(map #(+ % x) ints))
Both of these solutions basically apply the use of a closure which is an important concept to know: it boils down to defining a function dynamically which refers to a variable in the environment at the time the function was defined. Here we defer the creation of plus-x (or the anonymous) function until x is bound, so plus-x can refer to whatever value is passed in to add-x-to-each.
You almost got it right.
There are several possible ways:
1.
(defn addXToEach[intCollection x]
(map #(plusX % x) intCollection))
#(%) means same as (fn [x] (x)) (be aware that x is being evaluated here).
2.
(defn addXToEach[intCollection x]
(map (fn [item] (plusX item x)) intCollection))
3.
(defn addXToEach[intCollection x]
(map #(+ % x) intCollection))
and then you don't have to define your plusX function.
Hope it helps!
You are applying map to one collection, so the function that map applies must take one argument. The question is, how is this function to be composed?
The function
(defn plusOne [singleInt]
(+ 1 singleInt))
... works. It is otherwise known as inc.
But the function
(defn plusX [singleInt x]
(+ x singleInt))
... doesn't work, because it takes two arguments. Given a number x, you want to return a function that adds x to its argument:
(defn plusX [x]
(fn [singleInt] (+ x singleInt))
You can use a function returned by plusX in the map.
It is when you compose such a function that you can use extra arguments. This kind of function, composed as an expression involving captured data, is called a closure.
For example, (plusX 3) is a function that adds 3 to its argument.
(map (plusX 3) stuff)
;(4 5 6 7)
As you see, you don't need to name your closure.
Specifically for + the following will also work:
(map + (repeat 4) [3 4 9 0 2 8 1]) ;=> (7 8 13 4 6 12 5)
Of course, instead '4' put your number, or wrap with (let [x 4] ...) as suggested above.
It might not be the most performant, although, I guess.
(conj coll x), for performance reasons, will add x to the end of some collections and to the beginning of other collections.
Is there a way to check whether the collection will be naturally add-at-end or add-at-beginning? I.e.
(conj-at-end? x) ; false for lists and true for vectors.
It is fairly easy to write my own, by checking if something is a vector or list, etc, but this is error prone in case there is a new collection added or something changes.
conj is a part of IPersistentCollection interface. This interface defines only three methods:
conj - adds new element;
empty - returns an empty collection of the same type;
equiv - performs equality checks.
So, there is nothing like conj-at-end?.
I don't think it could be implemented, either. For example, how would you define it for internally unsorted collections like hash-maps and hash-sets?
(conj #{1 2 3 4 5} 6)
; => #{1 4 6 3 2 5}
Does conj add to the beginning or the end of a collection?
The question only makes sense for a sequential collection, for which you can just try it:
Define
(defn conj-at-end? [coll]
(and (sequential? coll)
(= (conj (empty coll) 1 2) [1 2])))
Then
(conj-at-end? []) ;=> true
(conj-at-end? ()) ;=> false
and
(conj-at-end? #{}) ;=> false
We also need the corresponding
(defn conj-at-beginning? [coll]
(and (sequential? coll)
(= (conj (empty coll) 1 2) [2 1])))
Then
(conj-at-beginning? []) ;=> false
(conj-at-beginning? ()) ;=> true
and
(conj-at-beginning? #{}) ;=> false
Note that a set is neither conj-at-beginning? nor conj-at-end?.
This rather pat solution would be upset if, for example, clojure.lang.PersistentArrayMaps, produced by array-map,
were stable under conj, which they are not, and
elected to comply with the empty clojure.lang.Sequential interface,
tested for by sequential?, which they do not.
I have a function that, given a vector, returns all unordered combinations:
(defn combination [ps]
(loop [acc []
ps ps]
(if (= 2 (count ps))
(conj acc (apply vector ps))
(recur (apply conj acc (map #(vector (first ps) %) (rest ps)))
(rest ps)))))
This works just fine, but seems a bit convoluted to me.
Is there a more straight-forward, idiomatic way to accomplish this in Clojure? I'm happy to use a Clojure core or library function, as this is certainly part of my definition of "idiomatic". :)
Clojure has clojure.math.combinatorics which contains many convenient functions. So arguably the "idiomatic" way to do what you did in Clojure would be to import/require clojure.math.combinatorics and then simply call combinations with n = 2.
...> (comb/combinations [1 2 3 4] 2)
((1 2) (1 3) (1 4) (2 3) (2 4) (3 4))
For this to work you'll need to first add the correct dependency.
As I write this the latest version is: [org.clojure/math.combinatorics "0.0.7"]
I did then require it ":as comb":
(:require [clojure.math.combinatorics :as comb]
In case you don't want to use math.combinatorics, you can edit your question to precise it and I'll delete my answer.
Your code returns all selections of two elements taken in order. Another way to do this is ...
(defn combination [s]
(let [tails (take-while next (iterate rest s))]
(mapcat (fn [[f & rs]] (map #(vector f %) rs)) tails)))
This is shorter than yours and is lazy too. But it's likely to be slower.
Somewhat facetiously ...
(defn combination [ps]
(clojure.math.combinatorics/combinations ps 2))
... which is lazy, but the source code is two or three times as long as yours.
If I have a matrix defined as:
(def m1 [[1 2 3][4 5 6][7 8 9]])
How do I go about counting the vectors within the vector in clojure. I know that (count m1) will return 3 which is the number of vectors I have in the initial vector but I can't remember how to count the inner vectors (its been a very very long time since I've had to deal with any lisp dialect). Also I do not want to flatten the vector and then count it because I need to count the values separately (ie. I want to return 3, 3, 3 because each of the inner vectors have 3 elements. One last restriction I guess is that I want to do this without using map right away because I realized I can simply do (map count m1).
That's actually very simple, just call:
(map count m1)
Or if you want to have your result also in vector:
(mapv count m1)
You'll want to use map. It will apply count to each element in the vector and return a list of counts.
(def m1 [[1 2 3][4 5 6][7 8 9]])
(map count m1)
=> (3 3 3)
Your edit: "I want to do this without using map."
(defn counts [vs]
(loop [vs vs, cs []]
(if (empty? vs)
cs
(recur (rest vs), (conj cs (count (first vs)))))))
One answer quite good but use count. Assume not using count and also not use map
((fn [lst]
(loop [l lst, n 0]
(if (empty? l)
n
(recur (rest l) (inc n)))))'(1 2 3))