Skip to content

Latest commit

 

History

History
192 lines (149 loc) · 6 KB

2020-07-02.md

File metadata and controls

192 lines (149 loc) · 6 KB

Learning Clojure in Public - Week 2 Day 4 (11/35)

Expectations

Today I am starting Clojure for the Brave and True. My expectation is to skim chapter 1 & 2, and to read chapter 3. I will only take notes about the things that are new to me, or that I feel should be repeated for the sake of me learning them.

What I learned

Datastructures review

Since I am only writing little tidbits of information I will use bullet points:

  • When using an if, the else expression is optional
  • do groups expressions together, useful if you need to do several things in the then statement of an if
  • when is a like the combination of if and do, it's taking a binary expression and will evaluate all the other arguments if it is true
  • or and and are interesting in the sense that they will return the respectively the first and the last truthy value
  • In Clojure, you bind a name to a value with def. As opposed to JavaScript it is encourage to assign and re-assign (a lot less in TypeScript I found out). In Clojure you end up using functions and not modifying the symbols. There is usually not equivalent to reassigning in place in a datastructure.

Summary of types and datastructures

  • numbers
  • string
  • maps {} (similar to hashes or dictionaries in other languages)
    • they can be nested
    • there are hash-maps and sorted-maps
    • hash-map creates a map: (hash-map :a 1 :b 2)
    • can also be used as a function to retrieve a value: ({:a 1} :a) => 1, but also (:a {:a 1}) => 1
  • keywords :a
  • vectors [1 2 3]
    • you can also use get on them, with the index as the second argument
  • lists '(1 2 3)
  • sets are collections of unique values #{"hello" 1 :hi}
    • hash-set creates a set
    • to get a value you can use contains?, get, or use a keyword as function

Functions

  • Functions that can take a function as an argument, or return a function are higher-order functions.
  • It is possible to define multiple functions depending on how many arguments you pass to a function:
(defn multi-arity
  ;; 3-arity arguments and body
  ([first-arg second-arg third-arg]
     (do-things first-arg second-arg third-arg))
  ;; 2-arity arguments and body
  ([first-arg second-arg]
     (do-things first-arg second-arg))
  ;; 1-arity arguments and body
  ([first-arg]
     (do-things first-arg)))

It's also a way to define default arguments:

(defn x-chop
  "Describe the kind of chop you're inflicting on someone"
  ([name chop-type]
     (str "I " chop-type " chop " name "! Take that!"))
  ([name]
     (x-chop name "karate")))

Destructuring

You can bind names to values within a collection:

(defn destruct
  [[a b & c]]
  (println (str "1 " a))
  (println (str "2 " b))
  (println (str "rest " c)))

You can also destructure maps:

(defn destruct-map
  [{a :a b :b}]
  (println (str "1 " a))
  (println (str "2 " b)))

=> (destruct-map {:a 1 :b 2})

An even shorter way is:

(defn announce-treasure-location
  [{:keys [lat lng]}]
  (println (str "Treasure lat: " lat))
  (println (str "Treasure lng: " lng)))

Using :as lets you retain access to the original map:

(defn receive-treasure-location
  [{:keys [lat lng] :as treasure-location}]
  (println (str "Treasure lat: " lat))
  (println (str "Treasure lng: " lng))

  ;; One would assume that this would put in new coordinates for your ship
  (steer-ship! treasure-location))

Loops

I have not covered loop yet.

(loop [i 0] ; initialize i at 0
  (printl (str i))
  (if (> i 4) ; here will stop the loop
    (println "end")
    (recur (int i)))) ; here we increment i and start the loop again

Loop has much better performance than a recursive call.

Clojure for the Brave and True Chapter 3 Exercises

1. Use str, vector, list, hash-map and hash-set

(str "hello " "world")
(vector '(1 2 3))
(list 1 2 3)
(hash-map :a 1 :b 2 :c 3)
(hash-set 1 1 2)```
#### 2. Write a function that takes a number and adds 100 to it
```clojure
#(+ % 100)

3. Write a function, dec-maker, that works exactly like the function inc-maker except with subtraction:

(defn dec-maker
  [n]
  #(- % n))

(def dec9 (dec-maker 9))
(dec9 10)

4. Write a function, mapset, that works like map except the return value is a set:

(defn mapset
  [f coll]
  (set (map f coll)))

5. Create a function that’s similar to symmetrize-body-parts except that it has to work with weird space aliens with radial symmetry. Instead of two eyes, arms, legs, and so on, they have five.

(defn matching-parts
  [part]
  #{{:name (clojure.string/replace (:name part) #"^left-" "top-")
   :size (:size part)}
      {:name (clojure.string/replace (:name part) #"^left-" "right-")
   :size (:size part)}
      {:name (clojure.string/replace (:name part) #"^left-" "bottom-left-")
   :size (:size part)}
      {:name (clojure.string/replace (:name part) #"^left-" "bottom-right-")
   :size (:size part)}})

(defn symmetrize-body-parts
  "Expects a seq of maps that have a :name and :size"
  [asym-body-parts]
  (loop [remaining-asym-parts asym-body-parts
         final-body-parts []]
    (if (empty? remaining-asym-parts)
      final-body-parts
      (let [[part & remaining] remaining-asym-parts]
        (recur remaining
               (into final-body-parts
                     (conj (matching-parts part) part)))))))

Takeaways

Overall it was a good revision of what I have learned in Clojure from the Ground Up. The order of things is a little bit different which is refreshing. Some things we didn't cover in CFTGU were covered at the beginning of the chapter (like loops).

I also did 5 out of 6 of the exercises in this chapter. They were quite easy but that makes sense as it is the fist chapter a beginner would study. Let's end the day with a tally of what I completed:

  • Chapter 3 of Clojure for the Brave and True
  • 5 problems included in the first chapter