(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.
;; notice that conjoining to a vector is done at the end
(conj [1 2 3] 4)
;;=> [1 2 3 4]
;; notice conjoining to a list is done at the beginning
(conj '(1 2 3) 4)
;;=> (4 1 2 3)
(conj ["a" "b" "c"] "d")
;;=> ["a" "b" "c" "d"]
;; conjoining multiple items is done in order
(conj [1 2] 3 4)
;;=> [1 2 3 4]
(conj '(1 2) 3 4)
;;=> (4 3 1 2)
(conj [[1 2] [3 4]] [5 6])
;;=> [[1 2] [3 4] [5 6]]
;; conjoining to maps only take items as vectors of length exactly 2
(conj {1 2, 3 4} [5 6])
;;=> {5 6, 1 2, 3 4}
(conj {:firstname "John" :lastname "Doe"} {:age 25 :nationality "Chinese"})
;;=> {:nationality "Chinese", :age 25, :firstname "John", :lastname "Doe"}
;; conj on a set
(conj #{1 3 4} 2)
;;=> #{1 2 3 4}
;; conjoin shows similar behaviour to cons
;; The main difference being that conj works on collections
;; but cons works with seqs.
(conj ["a" "b" "c"] ["a" "b" "c"] )
;;=> ["a" "b" "c" ["a" "b" "c"]]
;; conjoin nil with x or xs
(conj nil 3)
;;=> (3)
(conj nil 3 4)
;;=> (4 3)
;; maps and sets are treated differently
(conj {1 2} {3 4})
;;=> {3 4, 1 2} ; the contents of {3 4} are added to {1 2}
(conj #{1 2} #{3})
;;=> #{1 2 #{3}} ; the whole set #{3} is added to #{1 2}
(clojure.set/union #{1 2} #{3})
;;=> #{1 2 3} ; must use (clojure.set/union) to merge sets, not conj
;; When conjoining into a map, vector pairs may be provided:
(conj {:a 1} [:b 2] [:c 3])
;;=> {:c 3, :b 2, :a 1}
;; Or maps may be provided, with multiple pairings:
(conj {:a 1} {:b 2 :c 3} {:d 4 :e 5 :f 6})
;;=> {:f 6, :d 4, :e 5, :b 2, :c 3, :a 1}
;; But multiple pairings cannot appear in vectors:
(conj {:a 1} [:b 2 :c 3])
;;=> IllegalArgumentException Vector arg to map conj must be a pair...
;; And pairs may not be provided in lists:
(conj {:a 1} '(:b 2))
;;=> ClassCastException ...Keyword cannot be cast to ...Map$Entry...
;; Useful snippet: "merge" two or more vectors with `(comp vec flatten conj)`
(let [a [{:a "hi"} {:b "hey"}]
b [{:c "yo"} {:d "hiya"}]
c [{:e "bonjour"}]]
((comp vec flatten conj) a b c))
;;=> [{:a "hi"} {:b "hey"} {:c "yo"} {:d "hiya"} {:e "bonjour"}]
(conj nil 1)
;=>(1)
(conj nil [1 2])
;=>([1 2])
;; Conj new-element into nested structures "conj-in"
(def db {:users [{:name "Eduardo"}]})
(def new-element {:name "Eva"})
(assoc db :users (conj (:users db) new-element))
;; => {:users [{:name "Eduardo"} {:name "Eva"}]}
;; implement stack semantics with conj, peek and pop.
;; we start with a list
(def stack '(2 1 0))
(peek stack)
;; => 2
(pop stack)
;; => (1 0)
(type (pop stack))
;; => cljs.core/List
;; push = conj
(conj stack 3)
;; => (3 2 1 0)
(type (conj stack 3))
;; => cljs.core/List
;; now let us try a vector
(def stack [0 1 2])
(peek stack)
;; => 2
(pop stack)
;; => [0 1]
(type (pop stack))
;; => clojure.lang.PersistentVector
;; push = conj
(conj stack 3)
;; => [0 1 2 3]
(type (conj stack 3))
;; => clojure.lang.PersistentVector