Skip to content

Latest commit

 

History

History
102 lines (64 loc) · 4.34 KB

2020-07-06.md

File metadata and controls

102 lines (64 loc) · 4.34 KB

Learning Clojure in Public - Week X Day Y (15/35)

Expectations

Today is the beginning of week 3 of ClojureFam (how time flies...)

What I learned

Lazy Seqs

map is an example of a lazy function. It returns almost instantly and only when the data is accessed, does it apply the function it took as an argument. Every unrealized element has the recipe for realizing each element. Once an element is realized, it doesn't need to be realized again to be accessed.

However, Clojure chunks its unrealized elements when you try to access them. So if you try to access the first n elements of sequence, it will realize a bunch more as well.

Infinite seqs

To create infinite sequences, we use repeat and repeatedly (the latter taking a function).

The Collection Abstraction

into

into will turn the result of a seq function (it returns a sequence, a list) into another data structure. So for instance it can turn the result of a map taking a set back into a set.

(into {} (map identity {:sunlight-reaction "Glitter!"}))
; => {:sunlight-reaction "Glitter!"}

One more thing to note is that the first collection doesn't have to be empty.

conj

conj takes a vector, and one or several new elements to append at the end. It's very similar to into but takes rest parameter instead.

Function Functions

One thing I've wanted to do since I started learning clojure is taking a sequence and pass it to a function that takes rest arguments, like conj we just looked into. And the way to do it is with...

apply

apply does just that: (apply max [0 1 2]) => 2

partial

partial I am already fine with, it takes a function and arguments then returns a functions which can take arguments, and that new function will take the new arguments alongside the originally supplied ones:

(def add10 (partial + 10))
(add10 3)
; => 13
(add10 5)
; => 15

complement

complement is new to me. It simply inverts a predicate function so for instance you could do (def non-nil? (complement nil?)).

Brave Clojure Chapter 4 Exercises

Reloading the REPL

  • Load core.clj with (ns fwpd.core), reload with (use 'fwpd.core :reload)

1. Turn the result of your glitter filter into a list of names.

(defn extract-names
  [records]
  (map #(:name %) records))

2. Write a function, append, which will append a new suspect to your list of suspects.

(defn append
  [records new-suspect]
  (conj records new-suspect))

3. Write a function, validate, which will check that :name and :glitter-index are present when you append. The validate function should accept two arguments: a map of keywords to validating functions, similar to conversions, and the record to be validated.

(defn validate
  [keyword-to-validating-function record]
  (apply = true (map (fn [key] ((key keyword-to-validating-function) (key record))) (keys keyword-to-validating-function))))

4. Write a function that will take your list of maps and convert it back to a CSV string. You’ll need to use the clojure.string/join function.

(defn convert-to-csv
  [records]
  (clojure.string/join "\n" (map (fn [record] (clojure.string/join "," (map str (vals record)))) records)))

Takeaways

The content of the Chapter 4 of Clojure for the Brave and True were not new in itself (barely any new function for instance), but it went much deeper into why Clojure behaves the way it is, and why the core functions are what they are. I may still not be getting Clojure itself (why Clojure and not JavaScript for instance), but at least I am starting to understand some of the abstractions. Programming by abstractions definitely has a big appeal, forget about the nitty gritty of the implementation, and focus on what you want to achieve (for instance with the sequence abstraction).

Another takeaway that from today were the exercises: while the first two were super simple, the last two, while not being too complicated were challenging and interesting in the sense that they were mirroring things that I often end up scripting in JavaScript. More precisely string parsing and manipulating. For instance I recently started working on a tool that extracts specific items from a Roam Research backup. This is definitely something that I am starting to understand how to do in Clojure.