Contents
Expectations
My primary goal for today was to learn Clojure in a focused and efficient manner. I’ve been noticing over the last few days that my learning schedule has been quite erratic. This is probably due to my tendency to get distracted easily and work on multiple things at the same time. But I wanted to overcome this and set a realistic schedule for myself.
What I learned
Today’s learning material was Chapter 4 of Clojure from the Ground Up. This was a chapter that I was really looking forward to since it handles recursion and sequences. As I mentioned in my post yesterday, I wanted to crystallize my understanding of recursion and using functions that operate over sequences.
The sheer number of functions in Clojure’s core library that handle sequences ( take, repeat, iterate, repeatedly, cycle, interleave, partition, group-by and more!) blew me away. It really does seem like there’s a specific function for anything you might possibly need to do over a sequence or collection. And since most of these functions produce lazy sequences, the computation is only done when it needs to. Another interesting thing about these lazy-seq
‘s is that they invoke the underlying expressions only on the first call, and cache the result for future calls.
Chapter 4 also handles recursion. Using cons
to recursively operate on a sequence is quite easy and the syntax mimics the mathematical form of recursion closer than some imperative languages. The book has an excellent example on how to use cons
and recursion to create your own version of the map
function.
(defn own-map [f xs]
(if (first xs)
(cons (f (first xs))
(own-map f (rest xs)))
(list)))
Here the base case is when xs
is an empty collection. When that happens, we return an empty list. The recursive step is when we call own-map
on the all elements but the first.
I found this explanation of recursion to not only be succinct but also eye-opening for how I approached it.
Recursion is folding an unbounded stream of computation over and over, until only a single step remains
On the note of unbounded streams of computation, normal recursion in Clojure allocates a stack frame for each recursive call. So if the computation is “unbounded”, our program will consume a significant amount of memory. Other programming languages use tail-call optimization to avoid this. In Clojure, however, there is no automatic tail-call optimization. Clojure does make a loop .. recur
idiom available to us which is non-stack consuming.
More 4 Clojure
I didn’t spend much time working on the 4Clojure problems today as I was more focused on working through Chapter 4 and understanding all the different concepts. I did however finish 6 more Easy problems that required the use of sequences. None of these problems were really as vexing as the ones from yesterday now that I’m more familiar with sequences and using reduce
to manipulate them.
Learning how to Learn
As I mentioned earlier in this post, a goal of mine was to learn how to learn in a focused and more efficient manner than usual. I remembered reading about Pomodoro Timers in a Hacker News posts and how they helped people (especially software devs) focus and get into flow states. Some of my cohort members also mentioned that they’d found it useful. So I gave it a shot and I found it quite useful for concentrating. I was able to achieve a nice hour and a half of focused learning.
One thing I’m struggling with now is organizing what I’m learning into a single place. Currently, the way I take notes is quite scattered. I maintain some info in an Obsidian Vault using the zettelkasten method. However, I end up writing most of what I learn as comments in the code. This has the benefit of co-locating code and insights into a single place. At the same time, I lose the benefits of using a system like Obsidian in the first place.
Having said that, I am happy with the fact that I’m writing a lot more than I used to. This is the first time that I’ve ever written 4 consecutive posts. And I hope that I can keep this going with the support of my cohort.
Let’s end this day with a nice little tally:
- 6 4Clojure Problems
- Chapter 4 of CFGU
- Learned more about tail-call optimization
- 3 consecutive Pomodoro sessions
(repeat "See ya Tomorrow!")
You can also find this post on Notion.