ClojureFam
ClojureFam copied to clipboard
Ethan Plante's Progress
Clojure from the Ground Up
- [x] Chapters 1-3
- [x] Chapters 4, 6
- [x] Chapters 7, 8, 10
4Clojure
- [x] 20 problems
- [ ] 40 problems
- [ ] 60 problems
- [ ] 80 problems
- [ ] 100 problems
Clojure for the Brave and True
- [ ] Chapters 3-4
- [ ] Chapters 5-6
- [ ] Chapters 10
ClojureScript, Reagent, re-frame
- [ ] build an app with plain hiccup and JS interop
- [ ] build an app with reagent
- [ ] build an app with re-frame
DataScript
- [ ] complete http://learndatalogtoday.org/
- [ ] build an app with datascript
Athens Analysis
- [ ] figure out how Athens works
- [ ] note general structure
- [ ] note areas of greatest potential and the next step that might be taken there
#learninpublic
- [x] day 1
- [x] day 2
- [x] day 3
- [x] day 4
- [x] day 5
- [x] day 6
- [x] day 7
- [x] day 8
- [x] day 9
- [x] day 10
- [x] day 11
- [x] day 12
- [x] day 13
- [x] day 14
- [x] day 15
- [ ] day 16
- [ ] day 17
- [ ] day 18
- [ ] day 19
- [ ] day 20
- [ ] day 21
- [ ] day 22
- [ ] day 23
- [ ] day 24
- [ ] day 25
- [ ] day 26
- [ ] day 27
- [ ] day 28
- [ ] day 29
- [ ] day 30
- [ ] day 31
- [ ] day 32
- [ ] day 33
- [ ] day 34
- [ ] day 35
May 6, 2021 -- Day 1 of a New Start I read 1.5 chapters of Clojure from the Ground Up, taking notes on what seemed important, and I picked up some concepts that I completely glossed over last time:
- The language primarily uses lists, and that when a list begins with a verb, the list evaluates differently. (Duh, but even this didn't click last time.)
- I learned that programming languages are systems of types, with rules for how verbs work according to different groupings of types. (This ought to have been obvious to me a while ago, but it's enjoyable to gain new insights on the basics!)
My core problem last time was that I was trying to quickly skim through the resources and jump straight into programming, thinking that the concepts behind the skill would become apparent through aimlessly tossing code together. As obvious as this error was, I didn't see it when I attempted to learn Clojure the first time. Having observed this, I have more hope for this run!
Day 2
- Read Clojure from the Ground Up (CFGU) to end of chapter 3, skimmed 4 and found that I need to better understand 3 before I move on.
- 4clojure: did 9 problems (at this point, they're testing what I learned from CFGU)
Day 3 | Today, I read CFGU chapter 3 and the first chunk of 4 in more detail.
- Learned what let bindings, functions, def and defn do, and how special functions and Java code are the basic building blocks of Clojure.
- Started thinking more critically about solving problems (e.g. "How can we apply a function to more than one value at once?"). This reminds me of my days studying engineering, especially when I come up with my own solution before looking at his. This makes my studies much more rewarding.
- Realized I've heard the term "recursion" before, but that I still don't understand it. That'll be one of the first things I focus on when I start up again on Monday.
Day 4 | Read more of chapter 4, applying it and making puzzles for myself as I went. I solved a couple of these, and marked the rest with "[UNSOLVED]" in the comments of my Clojure file for this chapter. As I improve, I plan to revisit these and see if I have a new way to tackle these. They'll serve a similar purpose as the 4Clojure puzzles.
- I learned how recursion works, but I realize that I don't understand it enough to see all its implications (relevant problems that it helps solve). Any thoughts on this?
- Attempted 4clojure #19 again, but I'm a bit stuck. We have to find the last element in a list without using the "last" function. Is there a way to do this without loops, or am I ignoring the obvious? Additionally, is there a way to use recursion with "fn", as opposed to with "defn"?
Day 5 | Solved 3 4Clojure problems; read and experimented with concepts from a couple more sections in CFGU ch. 4; watched about 30 min of Rich Hickey's talks for context and help.
- Studied and practiced for about 3.5 hours total today. I'm not as efficient at learning this as I'd like to be. Breaks are important. Those'll start tomorrow.
- Got bogged down in trying to understand how to collapse sequences (part of ch. 4). Listening to Rich explain map and reduce helped a bit, but I'm still not quite clear on this. I'll revisit this tomorrow, particularly with a mind to doing the problems he gives. These will likely synthesize some of the concepts and functions in the chapter that are slowing me down.
- I'm still not really seeing use cases for a lot of these functions and tools. I have some vague sense that I'll be using them together to build more complex functions that do useful things, but I'm still lacking the context I need to see how that'll be done.
Day 6 | Studied for less time today, but I finished chapter 4 and did two of the problems it provides. (I imported the other two into my worksheet file for the chapter.)
- That bit about defining map in terms of reduce makes much more sense today. It just applies conj to each element in a list to create a new list. (Not sure why I wasn't getting it yesterday. Perhaps I didn't concentrate as much, or maybe I needed to sleep on it.) I think I was over-complicating reduce instead of thinking about how (doc reduce) defines it.
- Added some drills to my master notes list for Clojure that I want to incorporate as a regular practice to get me familiar with certain functions, how they work, and where to use them. (This is only the seed of that.)
- Took a 3-minute break after 30 min. Realized that breaks are most helpful when they're breaks from a difficult puzzle, whether it involves learning new concepts or solving defined problems. I'll need to keep that in my pocket. (This is unrelated, but having been studying Clojure, this way of thinking about breaks makes it seem like a function!)
Day 7 | Didn't give myself enough time today to solve my problems. Wrote two of my puzzles down on note cards to carry around.
- Realized that (apply str x) solves an earlier puzzle I setup.
Day 8 | The most productive 3 hours I've spent on Clojure yet. I read CFGU chapters 5, 6, and half of 7, and perused the Athens codebase.
- I had wondered what (defproject ...) and (ns ...) meant in the code. As it turns out, the former is the project definition and the latter defines a namespace. (Realizing the bit about ns was really exciting!)
- Chapters 5 and 6 were very theory-heavy, so the benefit I got from them was exposure to terms that seem important (macros, closing over, state, mutability, atoms, delay, future, etc.). I expect these to resurface, specifically because I recognized them from when I glanced at Clojure for the Brave and True.
- Chapter 7 is pretty exciting, because it actually points me to doing something with the smaller functions that I've been learning about. I have a couple small-ish project ideas that I want to implement (something to help me drill Clojure and approach puzzles better; something to help me understand my own code), so hopefully, this chapter will give me some more direction as to how to approach these. And even if not, I'm not in a rush to make these. It'll just be nice to actually be building things!
Day 9 | Read CFGU chapter 7. Got some exposure to the process of data analysis and how to do this in Clojure, but I didn't comprehend it well enough to reproduce it.
Day 10
- Read CFGU 8, read half of chapter 9 and skimmed the rest.
- The most useful parts of these were the general problem-solving/exploring advice. This is one of the most generally relevant parts of this course so far. It reminded me of the document "Product Development at Athens", which describes principles for exploring problems.
- Did 1 4clojure problem. I find that I get stuck pretty quickly when I approach these. Do I just not know enough of the core functions that would help solve these problems?
Day 11
- Read chapter 10 of CFGU. The stuff in this chapter seems important for more abstract programming, but I'll revisit the concepts once I get there. I have more important topics to study at present, like the core functions. (This is why I plan to start Clojure for the Brave and True tomorrow.)
- Watched "Effective Programs" by Rich Hickey. This was insightful, and it gave me exposure to some more practical concepts like how the goal of code isn't the code itself, but what it actually accomplishes in the world, how the first difficulty of learning the language is understanding that everything is based around functions, etc.
- Scouted out a few resources from the ClojureFam readme. These are fairly complex, but I was glad to rediscover the flow chart "Contributing to Athens | Your First Athens Commit" (https://whimsical.com/contributing-to-athens-your-first-athens-commit-VdBCZ1d33pzXR7H7h9uAen). It gave me some direction, since I didn't know how to order my studies. Macros and polymorphism can wait. For now, I should focus on the basics.
:clap:
Day 12
- Scoped out chapter 3 of Clojure for the Brave and True (CB&T) to gauge how to read it, did 4 of the exercises based on what I learned from CFGU.
- Figured out how to run a Leiningen project. (I didn't have lein.bat in the folders for the projects I was trying to make before, and, oddly enough, project.clj didn't have :main in it. I think I was using the wrong Leiningen template.)
- Made my first interactive program!! I go to my clojure-coach subfolder, type
lein run, and it jumps straight into my code. The main function uses read-line (a function I learned today), takes an input from the command line, and responds according to what is typed in. This enables a really basic interaction, which is exciting, because it allows me to run Clojure scripts from the command line, and actually start making interactive programs. - Learned that
lein replworks in a folder even if you don't run "lein new" in it. I'm still not sure how this works, but it seems like all you need is to have lein.bat in the folder for this to work.
Day 13
- Read CB&T chapter 3 slowly, took good notes and tested out the ideas in the REPL.
- Incorporated some of the basic ideas into my project. (I realized the importance of understanding Clojure basics on Day 12 after getting my project to be interactive. I didn't know what to do after that point to make progress, so I'm thankful to have direction in this after reading today.)
Things that didn't click for me until today:
- "Do" is a very helpful function. I had been puzzled about how I was supposed to do complex things with if-statements until I discovered it today.
- The basic data structures in Clojure (especially maps and vectors) are good enough for a lot of different use-cases. Oftentimes, simpler is better.
- You can hold functions in a collection, and use them by getting them from that collection! For example, I wanted a Main Menu for the project I'm building as I learn Clojure. (The interactive one I first got working on Day 12.) I made a map of different names of functions with strings that say what they do. Eventually, I'll replace these with the functions themselves, since I now know I can.
- You can pass functions as arguments of functions! I didn't understand the significance of this--that functional programming is unique in its emphasis on, well, functions.
This sums up the core of many of my confusions so far:
"Those unfamiliar with this kind of programming think of functions as allowing you to generalize operations over data instances."
On this note: something I've noticed as I've been learning Clojure is that its emphasis on functions (or "verbs") has made me pay more attention to the syntax of the English language. It seems as if functional programming is much more linguistic in this sense than other programming "languages" that I've previously studied.
Day 14
- Read more of CB&T, experimenting in REPL as I went in order to understand the ideas.
- Experimented more with interactivity. My current puzzle is figuring out how to make a text interface that can be explored through typing, but that has hidden aspects. (So something like a really basic text-based game framework.)
Things that Clicked
- If you're defining a function with multiple arities, each case needs to have parentheses around it.
- You can customize the arguments section of a function definition (defn [this thing] ...) to interpret different data types like vectors and maps. This is called destructuring, and the name makes sense since this interpretation requires taking apart the pieces.
Day 15
- Read more of CB&T, with some experimentation. I learned that loop and recur allow you to do recursion, and save you a bit of typing.
Day 16
- Similar to yesterday. Read more of CB&T, wrote out the given code in my editor, and analyzed it in order to understand.
- I remembered that reduce expects two arguments: an inital value (or the first thing in the given coll), and the next value in the sequence. This slightly helps me understand reduce, but I'll have to revisit this tomorrow. I remember being confused about reduce when reading CFGU.
- I'll also need to do more testing and experimenting tomorrow. It would help me better understand the core functions involved.
Day 17
- Made a note for functions and terms that I either do or don't understand called Clojure Dictionary. This'll help to guide my experimentation and learning. (I want to use this to incorporate reviewing and learning Clojure functions into the project I'm working on.)
- Read to the end of chapter 4 of CB&T. Skipped the harder exercises for now.
- Briefly experimented with reduce and regexes.
- Started chapter 5. This should help me out with the more theoretical questions I've had.
- Learned that
map,reduce, and similar functions work on any data structure that can work sequentially.
Day 18
- Worked on a personal Clojure project: wrote about what I wanted it to do (basically, I want to enjoy digital content but with constraints--like a word count), brainstormed implementations (where I realized that I could get the basic setup going with data structures), experimented (where I realized that I don't know data structures well enough to get the basic setup going)
- Learned how to include other namespaces:
(ns name-of-this-space (:include [other-ns])). I got stuck at first because I didn't realize that the :include bit needed to be wrapped in parens, or that the part inside needed brackets. - Looked into babashka, watched a talk on it by its creator. (It's pretty neat--it looks like it allows you to run clojure scripts from the command line or from bash)
- Solved 9 4Clojure problems
Day 19
- Read more of CB&T, ch. 4. Learned that Clojure emphasizes working with abstractions in order to keep programmers from getting bogged down in the details of different data structures. I see the advantage to this--if these structures are similar enough that they can be abstracted to a single thing (e.g. "seq"), then functions can be defined in terms of that thing, which saves a lot of time and thinking prevents spending time on solving the same problem in different ways.
Day 20
- Solved 4 4Clojure problems.
Today, I learned something really important about solving problems.
I spent a while on one of the easier 4clojure problems. The goal was to take a sequence of keywords (like [:a :b :c]) with a value (like "hello") and output a seq that paired the value with each keyword ({:a "hello" :b "hello" :c "hello"}, in this case). I approached this by starting to make a full-fledged function without clarifying the details of my approach, and by using reduce, which I didn't fully understand going into it. Naturally, it didn't work. (And I'm glad for that.)
After this, I started by testing into in a really simple way until I got it working. Then, I added a let binding. Then I made that into a function that worked on the first input item, then I made that function work for the first two input items, and then I realized I needed recursion, so I tried to introduce reduce (still not fully knowing how it worked). That last part failed, so I varied my approach and used map instead. After a few more iterations, I got it working.
What I gained from this process of testing was a very valuable lesson: figure out the core of the program, get that part working, then layer over it as you go. Implement the core of your approach and get it working. If that works, add a single layer to it.
On a different note, I've run into a similar problem when I've written poetry in the past. I would try to capture an entire experience or idea without first making sure I was really clear on what I was trying to capture. I would try to put this vague understanding into meter and rhyme with a scarce set of lines, but it wouldn't communicate what was in my head. I couldn't condense the experience into a poetic form because I didn't have clarity on the experience. But when I take something I'm really clear on and try to condense it down, it's a lot easier to do.
It seems like the parallel is that in both poetry and code, you test your understanding (of an experience, idea, or solution) through writing. And the more clear, condensed, and deep the result is, the better this understanding was.
Day 21
- Solved 2 4Clojure problems, worked on 2 others.
- Practicing solving problems is challenging, but I'm enjoying it. In one of Don Norman's talks, he says that simplicity in design is difficult to arrive at. I've found this in designing and testing solutions to 4Clojure problems. It definitely makes me see the importance of learning Clojure theory (which I've come to call Clojurology ;). I'm finding that my knowledge of functions is quite limited, and that drives me to learn more. Tomorrow will be more theoretical reading, study, and testing.
Day 22
- Just reading [[Clojure for the Brave and True]], ch. 4
- Wrote out recall questions about both concepts and how they were applied to solve certain problems. Experimented a bit by extending these out into new uses.
- Learned that map can be used on multiple collections (a mind-blower), collections of functions, and can use a keyword on a collection of maps to return their corresponding values.
- Learned that
seq {:key1 val1 :key2 val2}returns([:key1 val1] [:key2 val2]), which continues to boggle my mind. I'll need to revisit this tomorrow. - Dealing with problem-solving, recall, and concepts I don't understand makes me really want to be able to make a program for dynamic spaced repetition, that allows me to record my response. (Naturally, I want to name it "Clojurology".)
- The problem is that I don't yet know how to interact with a text file yet, or automate defining new values. Are these very difficult?
Day 23
- Read more of Clojure for the Brave and True, ch. 4
- Wrote up a handful of prompts to drill myself on concepts and how I've used them. I'm finding that these are quite helpful. They really make me concentrate on how a problem is being solved, which is exactly what I needed to make the learning more active and engaging. What I'll do is write down an example from the chapter on paper, then write it again in VS Code from memory. This has boosted my learning efficiency because it really works my understanding of the concepts and how they're used. (I'll need this--I'm on Day 23, and though I've gotten a good amount of exposure to these concepts, I'm only now digging more deeply into core functions.)
- I finally went back and figured out how
reduceworks. This gave me a good amount of clarity. Writing out thatreduce + [1 2 3]is the same as(+ (+ 1 2) 3)really helped. (Naturally, I wrote up a prompt for this in my digital notes.)
An Update, of Sorts It's been a few weeks since I've posted a Clojurology update. I'm on a hiatus from Clojure, since I'm working through Mark Rober's creative engineering course. I plan to resume once I finish.