Rohan Bansal


Learning to Think From First Principles

August 30, 2020


"We cannot expect to touch excellence if 'going through the motions' is the norm of our lives. On the other hand, if deep, fluid presence becomes second nature, then life, art, and learning take on a richness that will continually surprise and delight. Those who excel are those who maximize each moment’s creative potential—for these masters of living, presence to the day-to-day learning process is akin to that purity of focus others dream of achieving in rare climactic moments when everything is on the line." - Joshua Waitzkin, The Art of Learning

When I first saw Teach Yourself Computer Science (TYCS) pop up on Hacker News, I bookmarked it instantly. I was a big fan of the premise, to the point that when I moved out to San Francisco to start my first job, I took an in-person class by the makers of the site - Bradfield School of Computer Science - to try and deepen my understanding of computer architecture. It was a great experience, but I admittedly didn't think too much of computer architecture after that as I fell back into my work of translating business requirements into functioning web applications.

But recently, I was working on an implementation of some small feature in my Angular app when I had a minor 'epiphany' of sorts. I had recently read the book referenced above, The Art of Learning, and I sat back in my chair, wondering whether I really was just going through the motions in that very moment. You see, I spend a lot of time thinking about how to improve as an engineer. But in that very moment, I didn't feel like I was improving. I had spent nearly an hour debugging a small UI issue and had 25 tabs open. And sure, this is just the reality of programming one might say. But why couldn't I think about this problem at a deeper level? Was I being a lazy boilerplate programmer? Was there a deeper problem at hand?

I don't know the answer to any of the above questions. But since that moment, I've had an itch to just go deeper; to really think about things from first principles. That's what the most talented engineers I work with or watch on streams do. So that's where I would like to start. To encourage first principles thinking, I'm going to learn CS again from the ground up.

That's what this learning endeavor is; it's TYCS with a few modifications. At a high level, I'm going to be self-studying the following topics:

  1. Programming & Computation
  2. Computer Architecture
  3. Algorithms and Data Structures
  4. Mathematics (relevant to core CS AKA discrete)
  5. Operating Systems
  6. Computer Networking
  7. Databases
  8. Languages and Compilers
  9. Distributed Systems

I have a collection of resources I'm going to use to study these, but I don't want this project to just be about reading books. It's going to have an exercise focus, i.e. I don't just want to read about operating systems, I want to build a small one too. The books and papers should simply serve as stepping stones to the larger goal of building real things.

The following is the tentative plan of what I'm going to be working on. The format is roughly:

  1. Explanation of the topic and my current familiarity with it
  2. List of resources I will use
  3. The rationale for why I have chosen that resource (nested under each resource)
  4. The hands-on resources I will be doing to cement my understanding and keep things interesting

This page will be a 'living' page in that I will continually be updating it as my desires likely change.

Programming & Computation

What even is "programming" or "computation"? When I refer to programming, I'm referring to the mental process of considering the structure of programs. I'm worried I may have missed some beneficial programming models while first learning to code, so I want to go back and cover my bases. As for computation, I'm trying to understand how our CS "ancestors" arrived at the conclusions that made all of this possible.

Resource(s)

Hands-on

Computer Architecture

One of my favorite subjects in CS. I love learning the nitty gritty details of how a computer actually works at the most fundamental level.

Resource(s)

Hands-on

Algorithms and Data Structures

A topic I learned to love in my senior year after grinding LeetCode questions for hours upon hours. Consider it a less malicious form of Stockholm Syndrome.

Resource(s)

Hands-on

Discrete Mathematics

Not my favorite subject. That's why I've picked a lighter title to start, some well explained notes and then something a bit more heavy for the main course.

Resource(s)

Hands-on

Operating Systems

Something I've never touched before but am excited to dig into.

Resource(s)

Hands-on

Computer Networking

A topic I'm a bit ashamed to say I don't have much exposure with as I spend most of my day benefitting from the advantages this subject has bestowed.

Resource(s)

Hands-on

Databases

Another one I've studied and am looking forward to tackling again - the databases class I took in school was my favorite CS class.

Resource(s)

Hands-on

Languages and Compilers

I have zero experience here, but am interested in learning more as I would like to create my own mini-language (intended for personal use) eventually.

Resource(s)

Hands-on

Distributed Systems

My only exposure has been through work, but from what I know, it's exciting and I want to dive deeper.

Resource(s)

Hands-on

Order?

This one is tough and I'm sure it's going to constantly keep changing. It's tough because I know what would be immediately beneficial to me (Pragmatic Programmer, Clean Code, Design Patterns, etc) but I don't want this learning endeavor to just be solely about being a better programmer, although that's certainly an important part. I want it to also be about being a better computer scientist. And I'm admittedly much more excited about diving into the CS components.

So here's what I'm tentatively thinking:

I'm leaving the below list here for posterity; this was the initial roadmap when I first set out on this challenge:

  1. Code
  2. Nand2Tetris
  3. The Algorithm Design Manual
  4. Annotated Turing
  5. Computer Systems: A Programmer's Perspective
  6. Structure and Interpretation of Computer Programs
  7. The Pragmatic Programmer
  8. How to Solve It
  9. László Lovász's discrete math lecture notes
  10. No Bullshit Guide to Linear Algebra
  11. Architecture of a Database System paper
  12. Database papers
  13. Operating Systems: Three Easy Pieces
  14. Lions' Commentary on Unix
  15. Computer Networking: A Top-Down Approach
  16. REST dissertation
  17. Crafting Interpreters
  18. Data and Reality
  19. Designing Data-Intensive Applications
  20. Design Patterns
  21. Clean Code

Methodology?

Consistency will be key here. I'm hoping to do 2 hours during weekdays and 4 hours over weekends, every day, until completion. Inevitably, I will miss days. Regardless, I hope the knowledge will compound on itself such that future topics are more easily learned (i.e. after learning computer architecture, databases makes much more intuitive sense and I save time as a result).

Final Words

I'm ultimately doing this for myself, but I like posting on my personal website like this because it lets me gather my thoughts into a coherent structure before executing on an idea.

So I'm going to write posts when I finish topics, and I'll write posts reviewing the projects and implementations I work on. I'm excited to get started.

← More musings