Pitfalls to avoid as a programming noob

tl;dr

"Where to I get started learning how to program?"

There are 3 correct answers; more detail below:

  1. SICP: Structure and Interpretation of Computer Programs, by Abelson and Sussman.
    • There is a video lecture series
    • There is also a book, more or less identical to the lectures, which you can read for free online, either in html format or PDF
    • I strongly recommend watching the first lecture in SICP, irrespective of which path you choose. It’s one of those lectures you can watch 100 times and learn something new each time. I strongly recommend this so strongly that I’m going to video embed it here so you get distracted and watch it instead of reading this article:
    • You probably want Racket to play around with the code examples (tip: type them in by hand, do not ever copy-paste).
  2. K&R: The C Programming Language by Kernhigan & Ritchie.
    • You can find free PDFs online if you Google the title, or you can just buy a print copy.
  3. Erlang

About this article

The purpose of this article is to help beginners avoid the pitfalls that every other "how to learn to code" article recommends.

I wrote this pretty quickly so there’s not a lot of handholdy tutorial instructions, because those take a long time to curate.

I’m also putting aside the question of whether or not the world needs more programmers and the fact that the programmer labor market is probably permadead.

Definitely comment or reach out with questions or feedback.

There’s a section at the end with feedback from smart people I respect who disagree with me.

It’s worth reading what they have to say and why they think what they think. The point of this article is to give you a roadmap around mental quicksand.

However, there’s a reason most people recommend the quicksand approach.

The reason is that, generously, 5% of the population has the mental hardware necessary to be a great programmer. Realistically, it’s less than 1%.

My suggestions are really a filter. Only people in that 1% are going to be able to get through.

Statistically, you, the reader, are probably not in that 1%. Don’t feel bad if you’re not. Being in that 1% is a matter of winning the genetic lottery, not like discipline or focus or something.

Only 1% of the population has the mental hardware necessary to be a great programmer. However, 30-40% of the population has the mental hardware necessary to be a mediocre programmer. The Python/JS lake of quicksand path is really for those people.

My attitude is that it is super important, for everybody, especially people in the 99%, that people in the 1% don’t get fed into the lake of quicksand.

I don’t mean to discourage you. Learning how to program even at a very elementary level is quite beneficial because it teaches you how to think and how to articulate your thoughts.

You have an idea that seems super clear in your head. You have to explain it, with 0 ambiguity, to the dumbest thing in the world: a computer. You’ll find that this is much more difficult than you think, and that your ideas aren’t nearly as clear as you thought. Going through this very painful process over and over and over again is super beneficial.

If you are doing something that works for you keep doing that

Ultimately, the way you get better at programming is to sit in front of a computer and program. Don’t get too obsessed with doing things the perfect way (this is also a good strategy for programming, BTW).

If you like hacking minecraft or writing GeoGebra scripts to draw animated dicks with epicycles, and that gets you in front of a computer solving problems, keep doing that.

Pitfall warning: don’t waste your time with Python and JavaScript

The most common answers for "how to learn coding" are JavaScript and Python, both of which are wrong.

The reason people recommend those languages is they give beginners visible results very quickly, without having to learn how anything works. "Tits on the screen" is the technical term.

The problem with this approach is that you only learn how to program things that don’t require knowing how anything works.

These scripting languages are excellent for writing programs that are conceptually simple but actually involve a lot of not-obvious detail.

An example would be a program that reads a CSV file, gets the 9th column, parses each value as a decimal number, and then computes the mean and variance of the column.

That’s like a 20 line program in Python, and it’s easily a 100 line program in C. The reason is that the actual mechanics of what the computer is doing there (that is, what you would express in C) is quite nontrivial. Python allows you to "just read a file" and "just split the file by lines" and "just split each line by commas" without having to worry about what the computer is actually doing.

Python allows you to speak in terms of more abstract concepts rather than concrete computer instructions.

At some point, you’re going to want to do something that’s complicated enough that you actually have to know what the computer is doing. In Python this occurs the moment that you have to look up what a "deep copy" is. Gradually then suddenly, you pay the price for all that so-called "simplicity" that Python gave you.

These "easy" languages trap you in these mental prisons that you may never get out of. The most pernicious mental prison is "object-oriented programming". Why OOP is a mental prison is a long rant beyond the scope of this article. All you need to know is that OOP is a mental prison.

The problem is the map/territory problem: you begin to think that the OOP conceptual lexicon is the sum total of concepts in computing. That’s not just not true, it’s cancerously false.

Because you’re going to get better, and you’re going to get confident, you’re going to branch out and learn a few other scripting languages. You’re also going to learn Ruby, Lua, some JavaScript, and maybe even Java. You’re a sophisticated polyglot programmer now. You know all these different languages. And they’re all the same language with some minor aesthetic variation. And you don’t know that.

This confirms your "knowledge" that your job as a programmer is learning about design patterns and best practices for writing AbstractMetafactoryClassFactoryBootstrapFactorys and whatever the fuck "dependency inversion" is.

At no point in this process will it occur to you to stop to ask either

  1. what is the computer is actually doing?
  2. is this conceptual lexicon a good one?

On my suggestions

This brings me to why I picked the options I picked.

  • C teaches you how a modern computer actually works. It’s super important to understand that C is the language of how modern computers actually work. They don’t have to work that way. They work that way because of historical accident, not because C is the natural God-given language of computing.
  • SICP teaches you how to think about computation, and the theory of conceptual lexicons of computation, in general. C teaches you the practice of surveying. SICP is geometry.
  • Erlang has a very unique conceptual lexicon, which is the best I’ve seen for writing large, serious, nontrivial programs that actually have to work. What you’ll start to observe is an idea called Virding’s Law: all programs over time become shitty versions of Erlang. The reason is that every project, as it matures, has to solve the problems that Erlang solves. And Erlang does it better. I can’t explain the idea in a way that makes sense for beginners.

SICP

The reason to pick SICP is if you want to take the longer road of really digging into the fundamentals and concepts and really understand the big picture the right way the first time.

SICP is one of these books/lecture-series that bends your brain and fucks with your head. It has minimal direct application but radically sharpens the way you think, mostly in ways that have nothing to do with computing.

The reason to go with SICP is if that’s your thing.

The reason to not go with SICP is if you want to just get shit done. If you just want to get shit done, C is the thing for you, or maybe even Python/JS/Lua/etc.

SICP uses a language called Scheme to illustrate its ideas. Scheme is objectively a terrible language for actually trying to do real things.

The central thesis of SICP is that the core part of the field of computing is in designing formal languages to talk about a problem domain.

Scheme is an excellent language for fucking around with language design. It’s terrible for pretty much every other task.

By analogy, the important part of Newton’s study of motion was the development of Calculus, the mathematical language to express statements about motion. The ability to solve problems related to planetary motion was incidental.

There is a general theory, an array of techniques and principles, that go into how to design these mini-languages properly. That’s what SICP is about.

The reason that I recommend SICP is that I want you to think about programming from this perspective. It makes you a better programmer and sharpens your thinking overall.

It teaches you how to organize your thoughts and how to systematize your thinking. That’s the real benefit of learning how to program. It’s not that you make money or can make the computer do things. Those are bonuses. The really important things you learn from programming have more to do with clearly expressing your ideas.

Another reason is that if you use Windows, getting a Scheme environment working is much easier than getting a C compiler working or getting Erlang to work.

K&R

The reason to pick C is if you’re like a super hardcore person who likes doing things the hard way and also doesn’t like head-in-the-clouds abstract things and just wants to know how things work.

The reason to not pick C is if you’re not like that and want something gentler.

Me recommending C for beginners is like your grandfather teaching you how to swim by throwing you in a lake and then walking away.

You’re either going to drown or come out an excellent swimmer. From my perspective, both outcomes are positive. Maybe not from your perspective.

Erlang

The reason to pick Erlang is that Erlang is very Scheme-like, but it’s a much more restricted, smaller, simpler language, and it’s an excellent language for getting shit done. That’s why Erlang.

The reason to not pick Erlang is that Erlang is not very muggle-friendly. The tooling is terrible. All the documentation etc is oriented towards people who are already excellent programmers. You basically have to personally know expert Erlangers if you want to learn Erlang.

Terminology: "low level" versus "high level"; or: "it’s all C"

These "level heights" refer to degrees of abstraction, not difficulty or social class.

The levels are roughly

"High level languages" (Python, Erlang, Lisp, etc)
|
C
|
Assembly
|
Machine code

See, Python isn’t really a language, Python is a program (written in C), called the "Python runtime". You give the Python runtime instructions in a "programming language" called Python. But underneath it’s really just C.

Erlang works the same way. So does Java, so does Scheme, so does JS, etc.

Other common beginner suggestions I didn’t think of and my opinions of them

Haskell

Some people recommend these super mathy abstract languages like Haskell for total beginners.

These people recommend Haskell for reasons that rhyme with why I recommend SICP: the language itself is objectively terrible and useless, but it forces you to wrestle with a lot of really important ideas that make you a better programmer.

I disagree with this recommendation, but not strongly.

Haskell is a super important language to learn eventually simply because it has a lot of really weird counterintuitive ideas that have had major influence in other languages. An example would be that JavaScript’s async-await idiom is really just a special case of Haskell’s monad idiom, in disguise (post coming eventually).

Rust

Apparently, Rust is a common beginner suggestion now.

I disagree but not super strongly.

Disclaimer: I don’t know Rust or low-level programming super well. This is my perspective as an outsider.

Rust as a language is sort of a better version of C. C dates back to the 1970s. Today we know a lot more about language design, and we have 50 years of experience C being the king of the food chain, and we know the pain points of C all too well. And so we’ve learned a lot in hindsight.

Rust is like C with seatbelts and training wheels.

From a technical standpoint, Rust is excellent. There are some minor things I disagree with, but it’s not smoothbrain stupid.

The problem with Rust is purely social. The community around Rust is extremely toxic and self-destructive. I don’t expect the language to have much of a lifespan simply because its community is going to implode.

The advantage of Rust is that it’s very popular and so there’s a lot of handholdy tutorials out there.

Don’t use ChatGPT

I shouldn’t have to say this, and I’m definitely not going to explain why.

Feedback from better programmers

Feedback from S

This is a mathematician-brain type guy who mostly does low-level programming:

S:
    I've found that the people I told to just learn C, don't bother with
    Python, didn't get vary far, but all the reasoning you give for what's
    wrong with python is totally true. I wonder if a good compromise might be
    to say if you DO learn python, classes are not the prestigious advanced and
    better way of programming, they're a mental prison, and you should just
    write functions that manipulate lists and maps and tuples.

    if there were a "no libraries, no classes" python tutorial, or like SICP in
    python, wouldn't be the worst thing

    I also like rust as a learning language. C is indistinguishable from python
    for the first few chapters of any tutorial, and then suddenly you get to
    malloc and people get defeated, amp themselves up to try writing something
    anyway, get a seg fault, get defeated again, repeat

Me:
    Rust... disclaimer, I don't know Rust, nor am I knowledgeable about low-level
    programming enough to say this. But: Rust is one of those languages that should
    be avoided like the plague, purely on sociological grounds.

    Meaning if you write commercial software in Rust, it's commercial suicide,
    simply for the reason that you have to hire Rust developers

S:
    lmao

    basically you are recommending diving head first into barriers to entry,
    rather than being mindful of the fake shit and the sociology and so on

    it might be good advice tbh, but the trouble is the barriers to entry are
    fully real

Me:
    Yes. Part of my thing here is that the world doesn't need more incompetent
    programmers

    It desperately needs more competent programmers. The way to make competent
    programmers is to throw them at the barriers to entry

S:
    yeah fair enough

    I guess the people I was trying to help werent going to be very competent
    anyway


Me:
    That's a very important realization to come to terms with

    Not just that, but retards outnumber non-retards roughly 999:1. And so if
    you try to help retards, you end up treating the non-retards like retards,
    and then the non-retards only ever learn how to act like retards, and that
    actively hurts everyone, especially the retards.

S:
    classes and OOP best practices are basically the brawndo of programming

Me:
    omfg yes

S:
    classes have what code craves

Feedback from Z

Z is by far the most brilliant person I have ever talked to. One of these polymath people who is just brilliant and knowledgeable and thoughtful about everything. Also has a very cutthroat attitude towards the world.

People who are going to be great programmers are going to figure out how to be
great programmers, and giving them a heads up on the blind corners is very
sound and does indeed throw them straight at obstacles right off the bat.

But the cheapest price they (and you) can pay, is to weed the mediocre ones out
early.

There are a few (disappointing, depending on your perspective) studies on this.
TL;DR is that most people simply cannot become programmers and of those who can
learn programming very few will ever be any good at it.

I've had better luck with Erlang than Python when teaching kids.

Adults has been mixed. The people who become really good tend to dive into the
deep end with Erlang and wrestle with it and eventually like it way more. The
people who aren't so interested in actually solving problems tend toward
Python/JS and just want to get that happy feeling from making the screen do
things.

Kind of a frontend/backend mental difference.

I think the lack of invisible magic in Erlang is why it makes more sense for
kids. Also single assignment. The first time they realize they want a loop and
figure out how to write it themselves is magical. After that point they are
already dangerous.

Feedback from M

M is a professional TypeScript/JavaScript guy. He’s a lot more pragmatic.

I used to be such an elitist, then I had to work with real people

I completely disagree with your main point and I think that Python and JS/TS
are actually the right way. There are of course better ways (Swift), but  it’s
still the same kind of programming that is needed in order to ease a mortal
into programming. Your advice is good for a mathematician or someone who wants
to study CS rigorously.

But IMO there is a vast gap between the “muggles” and us. I have tried teaching
people programming and I have seen this over and over again. There are people
who already can program (just need to learn the syntax) and these people would
fare great with your advice. But these are not the muggles I am talking about.
The real muggles, who actually need to think really hard on concepts like “what
is a loop” (yeah, people initially don’t get it in actuality, even if they
claim they do), “what is a function” (or an abstraction in general), “what is
boolean logic” etc. So these “muggles” can only close this gap if they go with
something like python/js.

if we accept that programming cannot be teached if you don't have an innate
ability, then you are right. I am not sure I agree with that though.

It probably isn't a qualitative genetic trait, more like a learnable skill that
is very correlated with IQ and below some level it becomes (almost) impossible.

Though I have seen (2) people learn programming to a satisfactory degree and my
bets would be heavily against them (I would have lost money)

One thought on “Pitfalls to avoid as a programming noob

  1. I think it is worth mentioning why C++ and Java are terrible starting languages. It is important to speak that out not only because of how messed up they are, but also due to their disgusting popularity especially among fresh learners. Many schools and even universities (!) still teach those as first programming languages. Both C++ and Java (and C#, and alike…) are bloated as hell, and they actively make it hard to dodge some of those bloats, even on the most basic level. This essentially forces teachers to dismiss or workaround (unavoidable but perfectly valid) questions such as “what the hell is `while(cin >> x >> y) {…}` ?” or “why do I need a virtual destructor if it does nothing?”, because the answers are often complicated enough to effectively distract students from key points of a 101 programming course. The number of you-dont-have-to-think-about-it-now–s is just atrocious. I am basing that on my discussably pleasant experience of teaching some aspiring programmers C++ as their first or second language, and every time I had to provide an oversimplified answer to a complicated concern, something was dying inside of me.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.