Why I hate programming language intro tutorials

· ddrake's blog

or, I don't care how you write a `for` loop or Hello World

I hate the introductory tutorials for programming languages #

You decide to learn about a programming language that's new to you. So you go the main site for the language, and look up the usual kind of introduction, overview tutorial, Getting Started page, or similar.

Frequently, they begin with syntax. "Here are strings! Numbers! Booleans! And let's write 'Hello world'!"

Then they go on to describe how you write an if-then-else, or a for loop.

These documents seem intensely obsessed with these basic constructs, and with syntax.

But when I look at such a document, I don't care about those things.

The question I'm always asking is: what are the big ideas in this language? What's important? What is it good at? Why should I use this language, and when?

Context, my background #

I don't have a computer science degree, though I have taken enough upper-division undergrad CS courses so that, informally, I basically do. I haven't done graduate-level work studying programming languages.

I have been fascinated by programming since the 80s, and during undergrad and grad school (a PhD in math) I did a lot of coding. Later I worked for nearly 10 years as a software developer.

Programming languages are incredibly interesting to me, and deeply weird, in that they need to have two audiences: humans, and computers. The computers are unyielding in their demands and requirements for your code; humans, much less so, and the result is that all too often, we write code for the computer more than for humans -- and that, I believe, is a very poor choice.

My philosophy -- which I share with many others -- is that a programming language is indeed a language, just like human or natural languages, and it exists to communicate. I value language -- of whatever kind -- that effectively communicates ideas to other humans.

So, I often myself poking at new languages, or old ones that I don't know. And hence I often find myself reading "getting started" documents, or tutorials, or what have you.

And those documents -- written in the English language -- often don't communicate the ideas I care about.

Motivating example: experimenting with Racket #

I recently read Geek Sublime by Vikram Chandra; the book describes some amazing connections between natural and formal languages, and I learned a lot of cool stuff about Sanskrit.1 It really helps make the case that programming languages really are languages. The analogy is very deep and appropriate.

I also am reading Don't Teach Coding: Until You Read This Book which also really makes a case for the "language" metaphor, and uses Racket.

So, I've been poking at Racket. I use emacs, and have written lots of emacs lisp, so the overall syntax and so on for Racket are roughly familiar.

My questions #

So, I can load up DrRacket and type in code samples, and so on, but I kept thinking things like:

I don't have any deep or special background in programming languages, so I'm ignorant about these things. But I want to know!

Let's pick on Rust #

I hear about Rust all the time these days. Why is everyone using it? Why should I care about it, or learn it? Let's visit <www.rust-lang.org> and find out!

The page features a "Why Rust?" section. Excellent! Tell me why! Here's what the page says, and my snarky reactions.

"Performance: Rust is blazingly fast and memory-efficient: with no runtime or garbage collector, it can power performance-critical services, run on embedded devices, and easily integrate with other languages."

Well, so does C, when written well, right? So far you haven't told me Why Rust.

"Reliability: Rust’s rich type system and ownership model guarantee memory-safety and thread-safety — enabling you to eliminate many classes of bugs at compile-time."

Lots of languages have a type system. Many have guarantees of memory-safety and thread-safety. So that's nothing special. There is this ownership model stuff, what's that?

"Productivity: Rust has great documentation, a friendly compiler with useful error messages, and top-notch tooling — an integrated package manager and build tool, smart multi-editor support with auto-completion and type inspections, an auto-formatter, and more.""

Lots of languages have nice documentation. Elm is noted for its extremely friendly and helpful compiler messages. And lots of languages have really good tooling, package managers, and so on.

At this point, I don't really get the idea of Rust. Why did they make it?

My understanding of the ideas or "why" of Rust #

I don't know Rust, but here's what I do understand: one of the big ideas of the language is to eliminate memory leaks and race conditions automatically.

It does this when you call other functions by forcing you to declare whether the called function is allowed to modify the variable or not. That lets the compiler infer things about memory allocation, threads accessing shared memory, and so on, which means the compiler can throw errors for code that could potentially leak memory. That means if your program compiles, it means that code is guaranteed to not leak memory, because that's how the language's semantics and its compiler work.

That is useful to me. It tells me useful things; for example:

How the Rust book fails to do this #

On the Rust page, under "Get started with Rust", it links to "the book" and declares that it will give me an overview of the language. Sounds good! Let's look at the table of contents:

The Rust Programming Language
Foreword
Introduction
1. Getting Started
    1.1. Installation
    1.2. Hello, World!
    1.3. Hello, Cargo!
2. Programming a Guessing Game
3. Common Programming Concepts
    3.1. Variables and Mutability
    3.2. Data Types
    3.3. Functions
    3.4. Comments
    3.5. Control Flow
4. Understanding Ownership
    4.1. What is Ownership?
    ...

It's not until chapter 4 that you get to something I want to start with. If I'm doing initial exploration, I don't care about Hello World, or Cargo. I roll my eyes at the fact that you have data types, functions, comments, and control flow.

But ownership? That's new. What's that?

Here's an idea for a more useful structure. The Foreword does say something relevant -- it mentions memory management, and helping developers avoid pitfalls. Okay, that's getting towards the ideas I mentioned above.

The introduction is a mix of more non-useful generalities ("ooooh, it's for teams of developers! And for people who value speed and stability! How different from other languages!" </sarcasm>) and meta content about the book itself."

Let's imagine structuring the book like this:

The Rust Programming Language
Foreword
Introduction
1. What's Special About Rust?
    1.1 The Ownership Model
    1.2 ...other stuff unique to Rust, or that it's really good at...
2. Getting Started
    1.1. Installation
    1.2. Hello, World!
    1.3. Hello, Cargo!
3. Programming a Guessing Game
4. Common Programming Concepts
    3.1. Variables and Mutability
    3.2. Data Types
    3.3. Functions
    3.4. Comments
    3.5. Control Flow

Let me hasten to add that I'm super ignorant about Rust, and am surely missing things. And also that I don't mean to impugn Rust! It seems great, and I'm glad to see it being so popular. I'm just using this as a typical example of how this kind of communication -- call it promotion, propaganda, or whatever -- is done.

Better example: Clojure, Erlang #

In the vein of Lisp, Scheme, and Racket: I find the main page for Clojure a bit better -- it has a "rationale" document that answers the kind of questions I care about.

I can read that and see immediately that I'm getting: Lisp, functional programming, and something that runs on the JVM. Those are things that quickly tell me whether I care about Clojure or not.

For Erlang, the page makes it clear that it's about scalable, high-availability software. That's helpful! It tells me that for my rando little script...Erlang is likely not good. Nor for my data science code.

Let's pick on Julia #

Julia's home page reads much like the Rust one -- ooh, it's for high performance! It has debugging and profiling! -- though it does mention the multiple dispatch.

I've actually used Julia, and would describe some of the big ideas there as "it kinda wants to be a replacement for scientific computing languages like Matlab or R, done as a 'regular', full-featured programming language".

Beyond that, my understanding is that it's dynamically typed, and uses that typing to do smart stuff with multiple dispatch. I also get the idea that "multiple dispatch" can be thought of as a radically different approach to object-oriented languages, in which the focus is on different kinds of functions in the way that OOP focuses on different kinds of objects.

Tell me how to be a "native speaker" of your language #

What are the idioms, the conventions? What are the standard approaches?

For example, in Racket -- or Scheme, or Lisp, anything in that family -- recursion is favored over iteration.

So, you can write something that's like a for loop in those languages, but...that's usually not natural. It's not how a "native speaker" of that programming language would write it. It's working against the nature and the ideas embedded into the language.

For this example, instead of a for loop, the natural thing to do usually looks like this idiom: given your list,

  1. If it's the empty list, just return that.
  2. If not, do something to the first element of the list, and then recursively call yourself on the rest of the list. Use the processed first element and the result of the recursive call to return whatever you need to. (Often, you make a new list by prepending the processed first element to the result of the recursive call.)

So, if you're introducing me to Racket, or some related Scheme or Lisp dialect, go ahead and mention that there's loops -- but tell me that the idea in this language is to prefer recursion over iteration.

Tell me how to improve this essay #

I want programming language websites to better communicate ideas to me.

Likewise, I want to better communicate ideas to you, dear reader!

I'm keenly aware of the limitations of my knowledge, experience, and writing skills. Lemme know what you think: https://mathstodon.xyz/@ddrake or prose.sh@dandrake.org.


  1. I also achieved some stunning insight into the Buddhist philosophy of the nonexistence of the self, and of "dependent co-arising". Did not see that coming from a book apparently about coding and programming languages...! ↩︎

last updated: