'Recurse Center Journal: Week 1'

2020-08-14

# Slowing Down and Learning

This week I completed my first week at Recurse Center. Recurse Center is (in their own words): "[an] educational retreat for anyone who wants to get dramatically better at programming". After my first week I think I can safely say that it is a lot more than that too.

I'm attending a Recurse Center batch because I want to slow down and learn things. As a professional programmer you are rarely afforded the opportunity to stop and ask: "Why does write return the number of bytes written?" or "how exactly does a linker work?" At work it's usually sufficient to learn just enough to get by and move on to the next thing. After all: there's always more work to be done and not enough programmers to do it.

I'm writing about my time at Recurse for two reasons. First, I want to better retain all of the awesome things I'm learning while I'm here. In my experience, repeating what you've learned in writing is a great way to do that. Second, I want to become a better writer. I've always enjoyed writing, about technical topics or otherwise, but is also something I haven't been able to give a lot of attention to recently.

In service of slowing down and learning things I have a couple different projects I'd like to try working on. What they all share is in order to do them there is a lot I would need to learn. In order of concreteness:

  1. I'm really in to Super Smash Bros. Melee for the Nintendo Gamecube. People have used emulators to be able to play the game online and recently they made it even better with a technique called rollback netcode. It's basically branch prediction but for controller inputs (if someone is pressing A, assume they will keep pressing A until you hear otherwise. At the timescale of a computer you're usually right). I want to learn how exactly this works and maybe contribute in some way.
  2. I've learned a lot about build systems and it seems to me like there's room for a new build tool that's like Bazel but helps you write your config. Basically:

Start build tool

Within build tool run a command

The build tool uses strace/something to see what files it opened

Show the user the files that were opened, let them accept, decline, or edit them

Commit those as the new dependencies

Next time you use the build tool to run that command, it will only allow the command to read the files that were recorded as deps. This could be achieved with containers

This makes it easier to add new dependencies (just re-run the command in record mode) but also it could make it possible to catch when a command starts requiring fewer dependencies. Just sample the command in record mode and compare against the list of known good dependencies

  1. Build a gradually typed programming language that is designed from the ground up to be gradually typed. None of this "bolt on a type system to an existing dynamic language" business.

In order to do these things I'm (re)learning C++ (needed for the Gamecube emulator, also needed to really understand why Rust is the way it is which is what I would use for projects 2 and 3) and Haskell (I want to understand type theory better).

With that, let's dive in. I'm breaking this out in to the buckets where I spent most of my time this week. Some of these sections will be more fleshed out than others, sorry!

Windows Development Environment

I wanted to try doing most of my development on Windows at RC for three reasons:

  1. I use Windows to play Super Smash Bros via the emulator, so if I end up making change to it I would want to test them in Windows.
  2. I love learning things. I've never really used Windows for development, only Linux and macOS, so there are a lot of new tools I now get to try. I've heard great things about Visual Studio for example, but I've never used it.
  3. My Windows desktop is by far the fastest computer I have right now. I don't really want to invest a new laptop right now with the impending ARM invasion.

Visual Studio

I didn't end up using Visual Studio as much as I would have liked this week, for reasons that I'll get to. I did run in to one problem which is worth noting though. I had previously installed Visual Studio Community Edition to try doing C# web development a while back. This week when I started it up it prompted me for a license. I was a bit discouraged because not having a job at the moment meant I wasn't too keen to pay for a Visual Studio license. It turns out if you sign in with any Microsoft account you can continue use Visual Code no problem, at least for non-commercial stuff.

Hope to be able to talk more about Visual Studio in the future!

Windows Subsystem for Linux 2

Once I decided that I would need to refresh myself a bit on C++ before diving in to the Gamecube emulator codebase I found developing in Windows was slowing me down, so I switched to compiling and running my programs in the Windows Subsystem for Linux (WSL). It uses virtualization, but is super fast. I'd love to learn how this works and it seems like this talk might be a good place to start.

I've been really impressed with how well it works, especially when paired with Visual Studio Code. The new remote extension makes the experience seamless. If I open a project that's in WSL VSCode knows to:

  • Run extensions in WSL
  • Open terminals in WSL
  • Do builds, tests and even debugging in WSL

Most of the time I forget that Windows is involved at all. Most of the time. Also from some chatter on Twitter I'm seeing that there might be more monsters hidden here. If I run in to them I'll add them here. :)

OneNote

On a whim I started using Microsoft OneNote to take notes this week. This thing is seriously great. Maybe I'll expand on this in a later post but, if you're reading this and you have a Windows PC I think you have OneNote. Give it a shot, it's everything I've wanted in a note taking application.

C++

I learned C++ basics in college, and have used it in anger a few times since then, mainly when I was working on HHVM. So I've always felt like I knew the basic syntax and understood pointers. I learned a lot about how to debug CMake (that felt like what I spent most of my time on with HHVM) but I don't know a lot of the in between bits. I'm mostly interested in experiencing, viscerally, what Rust and Go feel that they are fixing about C++ so I can understand the trade-offs they are making better. So, I started from the beginning, working my way through the C++ programming language by Stroustrup and building a simple CLI application.

Smart Pointers

I realized that I had a misconception about C++ memory management. I thought that memory management in C++ was entirely manual, meaning that you had to free everything yourself. It's a bit more sophisticated than that. I think the rules are this:

  1. Anything that you create gets deleted/free'd when it leaves scope.
  2. Unless it was created with new, which returns a pointer
  3. However, if you wrap that in a smart pointer, that will be deleted when it leaves scope

What's a smart pointer? There are several types of smart pointers in C++:

  1. unique_ptr: Allows exactly one owner of the underlying pointer.
  2. shared_ptr: Reference-counted pointer.
  3. weak_ptr: Not really sure what this one is for yet. I don't think you're supposed to use it unless you really know what you're doing.

If you use a smart pointer as a member of a class, that will automatically be cleaned up when instances of that class are no longer in scope as well.

Many Different Ways to Initialize Things

There are, by my count, at least 6 different ways to initialize things in C++:

I'm not sure what all these are for yet, I need to read up on them more!

C++ Standards

I spent a lot of time trying to use the new filesystems library that was added to the C++ standard library recently. I say recently because ... I can't exactly pin down when it was added. Some documentation I've found says it was added in gcc 8, but I had to use gcc 9 to get it to work. Maybe this was related to how that library moved out of the experimental section of the standard library.

A lot of stuff has changed in the language since I learned it 10 years ago. I think the only two features I've used so far are lambdas and the filesystem library but I'm looking forward to seeing what else has changed.

Build Systems Conversation

  • Build tools are hard to understand. How to debug declarative things? Good examples like CSS. Where are the build tools visualizers?
  • Link to interesting links
  • Explain my idea for a build tool

I had a great coffee chat with someone where we talked about build systems and how hard they are to debug. We posited that this might be due in part to their declarative nature. Most built tools allow you to declare targets and their dependencies. You don't say "In order to build my app, build this binary, then build this other thing". You simply describe the dependencies.

This gets really hard to debug. If you build a target, and you expect another target to be updated but it isn't, what do you do? Unlike an imperative system you can't stick a printf in between two "steps" in your build process and inspect the state. This is a problem inherent in declarative systems.

One declarative language that does this well in my experience is CSS. Chrome and Firefox dev tools give you fantastic visualizations for how your CSS rules are affecting the layout in the browser. I think build tools should make visualizations a first-class part of the experience. Encourage people to generate graphs of their dependencies, of graphs of a given run, rather than hiding it in third party integrations.

Haskell/Functional Programming Study Group

I've tried to learn Haskell two times in the past.. Both times I gave up pretty quickly. I think I was frustrated by my inability to do simple things so much that I never got to the interesting parts. I think this time might be different.

The previous two times were in college and at a previous job. In both cases I was less experienced and more time constrained than I am now at Recurse Center. I've already asked a couple beginner Haskell questions at RC and gotten very helpful answers, so I'm feeling supported too!

I've also recently gotten the opportunity to learn two things from scratch: piano and skiing. In both cases I got to experience being really, truly bad at something. I was frustrated with myself. In both cases being frustrated didn't help, but welcoming failure and being comfortable with it did. Hopefully I can carry that experience over to Haskell as well.

Until next week: learn slowly and be comfortable with failure!