Here be the end of Week 3. Onwards to bigger things.
I finished up Chapter 8 today. Well, more like sped through it. Having gone through macros with Clojure from the Ground Up, I was inclined to get through the chapter quickly. But despite that there were still some interesting things I learned from the chapter.
- Need to quote expressions to get unevaluated data structures back in the final list
- Need to careful about the difference between a symbol and a value
- quoting produces an unevaluated data structure
(+ 1 2)
;; => 3
'(+ 1 2)
;; => (+ 1 2)
- the
'
character is a reader macro for the quote function - Syntax Quoting -> ``` includes the symbol's fully namespace
'+
;; => +
`+
;; => clojure.core/+
'(+ 1 2)
;; => (+ 1 2)
`(+ 1 2)
;; => (clojure.core/+ 1 2)
`(+ 1 ~(inc 1)) ;; using ~ inside ` unquotes the form
;; => (clojure.core/+ 1 2)
(list '+ 1 (inc 1))
;; => (+ 1 2)
`(+ 1 ~(inc 1))
;; => (clojure.core/+ 1 2)
Clearly the syntax-quoted version is more concise.
Macros receive unevaluated, arbitrary data structures as arguments and return data structures that Clojure evaluates.
Unquote splicing unwraps a seqable data structure, placing its contents directly within the enclosing syntax-quoted data structure.
`(+ ~(list 1 2 3))
;; => (clojure.core/+ (1 2 3))
`(+ ~@(list 1 2 3))
;; => (clojure.core/+ 1 2 3)
-
Variable Capture - Macro introduces a binding that overwrites an existing binding. Soln: gensym -> produces a unique symbol that can be bound to variables inside macros used to prevent variable capture within macros.
-
Double Evaluation - When a form passed to a macro as an argument gets evaluated more than once. Soln: Bind the repeating form to a
gensym
within a let and use that instead of the form
I'm getting a hang of solving these Medium problems. Today I managed to get through a couple more -
No. 50 Split by Type Write a function which takes a sequence consisting of items with different types and splits them up into a set of homogeneous sub-sequences. The internal order of each sub-sequence should be maintained, but the sub-sequences themselves can be returned in any order (this is why 'set' is used in the test cases).
(defn spl-by-type
[xs]
(into #{}
(vals
(reduce
(fn [acc v]
(assoc acc (type v)
(if-let [x (get acc (type v))]
(conj x v)
[v])))
{} xs))))
No. 55 Count Occurences Write a function which returns a map containing the number of occurences of each distinct item in a sequence.
(defn occur
[xs]
(->> xs
distinct
(reduce (fn [acc a] (assoc acc a (count (filter #(= a %) xs)))) {})))
Macros are fun. They can be used for a lot of things. But maybe don't use them for everything.
Today's tally -
- Chapter 8
- Watched Video on Datomic
- 2 more 4Clojure