on learning a new programming lang

This commit is contained in:
Wouter Groeneveld 2022-05-11 14:09:33 +02:00
parent 3e0360b6f4
commit d865cf3f0c
4 changed files with 78 additions and 4 deletions

View File

@ -10,7 +10,7 @@ tags:
Last month was [Analogue Pocket](/post/2022/04/analogue-pocket/) month. Since then I've been obsessed with mediocre Game Boy (Color) games that I somehow never played when I was young---or never managed to finish. Most of these old games don't come with a save system since soldering on an extra chip (RAM) meant increased costs. That could be solved by either artificially extending the gameplay thanks to a ludicrous difficulty, or by employing a password system (see for instance [Password Hacking Sylvester & Tweety: Breakfast on the Run](/post/2022/04/password-hacking-sylvester-and-tweety/)). My latest acquisitions: _Dragon Warrior Monsters_, _Tom & Jerry_, and _Elmo_ from Sesame Street. Only the first is worth playing, but I'm having fun nonetheless.
But where to store all those carts? Most sellers at [flea markets](/post/2021/06/flea-market-season) long tossed the feeble cardboard boxes from the pre-Nintendo DS era. And most professional retro game stores sell those for more than triple the cart price. For example, the black _Dragon Warrior Monsters_ Game Boy Color cart had me cough up`€35`, while a (PAL) version with original box would have easily been `€100`. Provided you manage to find it in the first place.
But where to store all those carts? Most sellers at [flea markets](/post/2021/06/flea-market-season) long tossed the feeble cardboard boxes from the pre-Nintendo DS era. And most professional retro game stores sell those for more than triple the cart price. For example, the black _Dragon Warrior Monsters_ Game Boy Color cart had me cough up `€35`, while a (PAL) version with original box would have easily been `€100`. Provided you manage to find it in the first place.
Another solution is needed. Fortunately for us, "The Internetz" already solved it: use **clear cassette cases**:
@ -18,7 +18,7 @@ Another solution is needed. Fortunately for us, "The Internetz" already solved i
These now probably useless plastic containers are a perfect fit for Game Boy, Game Boy Color, and Game Boy Advance carts. Except that the inside of those cassette cases have two plastic pins that fit the two holes of a cassette. You'll need to remove one of those (it doesn't matter which one). See above picture: the _Bugs Bunny in Crazy Castle_ cart takes op the upper space of the cassette case because of the lower pin that's still there. Removing the pin is just a matter of taking pliers, wiggling a little bit and watching out with the small plastic fragments that tends to crack easily.
I ordered over sixty clear cassette cases somewhere online instead of buying old cassettes on flea markets. Most of these plastic covers are black. Watch out with the dimensions: some, like mine, have rounded corners, which is actually _not_ what you want, since it's more difficult to push in the printed cover image.
I ordered over sixty clear cassette cases somewhere online (for Dutch people: [debandjesfabriek.nl](https://www.debandjesfabriek.nl/shop/norelco-cassette-box-super-clear/)) instead of buying old cassettes on flea markets. Most of these plastic covers are black. Watch out with the dimensions: some, like mine, have rounded corners, which is actually _not_ what you want, since it's more difficult to push in the printed cover image.
Once you get your hands on a bunch of cases and pulled out one pin on each of those, the Game Boy carts fit, congrats! The next part is a bit more difficult: adding a nice looking cover image as finishing touch:

View File

@ -0,0 +1,74 @@
---
title: On Learning A New (Programming) Language
date: 2022-05-11T13:04:00+02:00
categories:
- programming
- learning
---
The [Pragmatic Programmer bible](https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/) by David Thomas and Andy Hunt recommends learning a new programming language each year. Each new language comes with its own guidelines, style, devote followers, and approach to problem solving. The more languages under your belt, the more likely you'll be able to creatively combine and convert practices from one language into another.
Bruce Tate didn't like the recommendation of Andy Hunt and Dave Thomas. Just _one_ language, each year? Why not seven in seven weeks? In [Seven Languages in Seven Weeks](https://pragprog.com/titles/btlang/seven-languages-in-seven-weeks/), Tate not only helps jump-start seven languages, but also how to quickly learn any new programming language. Its success announced the inevitable follow-up four years later, _Seven More Languages in Seven Weeks_. Tate's books not only cover the technicalities of a language but also give the reader a taste of how other programmers across broadly different communities solve complex problems.
---
In [Fluent Forever: How To Learn Any Language Fast and Never Forget It](https://www.goodreads.com/book/show/19661852-fluent-forever), Gabriel Wyner---a polyglot that fluently speaks Russian, Italian, German, French, English, and less fluently en more---explains his secrets for quickly and efficiently mastering grammar. It's been since 2015 that I read the book, so I can only remember I was impressed, but a new question arises: is learning a new language similar to learning a _programming_ language?
Plenty of academic research exists on that topic: I could continue by citing papers that confirm this theory, but the fun doesn't stop there, as there are of course also papers that deny it. Theory aside, a few common critical thinking fallacies occur in both spoken and programming language learning. In a recent paper called _Here we go again: Why is it difficult for developers to learn another programming language_, researchers identified that what they call _cross-language clashes_ also occurs while learning a new programming language.
For instance, suppose you're a Java developer, and you're learning Kotlin. Here's a Kotlin expression for you:
```kt
val boundsBuilder: LatLngBounds.Builder =
LatLngBounds.Builder()
```
Would it be possible to rewrite the above? You could leverage your JDK experience: sure enough, type inference might also exist in Kotlin, so we could loose the `: LatLngBounds.Builder`:
```kt
val boundsBuilder = LatLngBounds.Builder()
```
No big surprises here---Kotlin also runs on top of the JVM. As a person speaking Dutch, I sometimes make faster progress learning German because they're both germanic languages that share (some) of the same syntax and etymological origins. With emphasis on _some_. My grandmother speaks a local Flemish dialect with lots of German loanwords. This is called cross-language _facilitation_: precisely _because_ you know one language, you're making much faster progress in the other.
Unfortunately, this trick doesn't always hold up. I know many programmers who struggle to master JavaScript that, although it contains the word "Java", has little to do with the language. It turns out that prototypal inheritance, variable hoisting and async functional programming is a whole different world compared to traditional object-oriented work on the JVM. This is called cross-language interference: precisely _because_ you know one language, you're making much slower progress in the other. Thank you, assumptions-driven cognitive brain work!
Cross-language interference also occurs in spoken languages. The Spanish word "embarazada" looks like "embarrassed" but I'd advice against using it in the same sentence since it means "pregnant". Whoops. There are plenty of such silly examples you can use to keep boring family members entertained at parties.
---
While we're at the subject of prejudices: learning a new programming language doesn't mean the _culture_ and _community_ that drives that language are the same. In my view, we as developers are all too eager to learn something new and shiny, without first considering a few important things:
1. Will this language solve my problem? What is its primary **purpose**?
2. What is the **infrastructure** like?
3. How **active** is the language?
4. How open is the **community**?
5. What is the language's **design philosophy** like?
6. What's the **history** behind the language?
For Q1, in a spoken language, it's obvious: to communicate with others. But not always: learning Latin will open the world to the ancient world through books by no longer relying on translations. There's no need to jump ahead and start learning Latin to be able to say _quod erat demonstrandum_ to your neighbor. For a programming language, this question is surprisingly difficult to answer and depends on many variables. For example, investigate languages such as Elixir if you require concurrency and message-passing at the get-go. Investigate something like Go if single native binaries are important to you. Check out JRuby, Clojure, or Kotlin if you already have critical things running on the JVM and want easy JVM interoperability. If you require a modern systems language with full control, check out Rust or Hare.
We're easily deceived when it comes to answering Q1. For instance, Go is said to be performant because it compiles to native binaries and you can use pointers---with the ease of a garbage collector. The modern [Caddy webserver](https://caddyserver.com/), implemented in Go, is 10x faster than Apache2. But also still slower than Nginx. And are we measuring the same thing here? Of course not. Performance is (almost) _never_ a great argument for picking one language over the other: this is an implementation issue, not a language issue. Don't write Python code because everyone does.
For Q2, I'm thinking about unit testing (awesomely integrated in Go), remote debugging, hot code swapping (shit in C but awesome in Elixir), security features, etc. A language is never just a set of keywords called the syntax: the tools that surround it are perhaps more important than the dialect itself. Is a package manager included? How about stress tests or support for extensive debugging like [Delve](https://github.com/go-delve/delve)?
For Q3, I want the language to be future-proof and stable. I don't want to change spelling every six months (ECMA Standard decision makers, I'm looking at you), but I don't want to end up with a dead language. The Dutch language had a few major changes in the nineties which was difficult to grasp without a guide such as [het Groene Boekje](https://en.wikipedia.org/wiki/Word_list_of_the_Dutch_language) (_the Green Booklet_). Luckily, for spoken languages, this is less prevalent. Imagine having to change syntax every few years... Guess what we as developers have to do every few years (or every week, seven times)!
Q4 is, to me, becoming more and more important. Nowadays, I don't want to choose a language just because I think it's cool and will fit my purpose: I want the community to be vibrant and friendly because I might be part of it. I might want to contribute. This is a very subjective feeling, and gauging it is perhaps a bit challenging. What kind of feeling does the main website and docs radiate? When attending a conference (or viewing a few videos online), how well are speakers and questions treated? If you're still having a hard time figuring out: check out the [Oracle Java site](https://www.oracle.com/java/), and now check out [go.dev](https://go.dev/) or [elixir-lang.org](https://elixir-lang.org/). You'll see (and feel) what I mean.
Q5 is very easy to visualize: try to generate a dependency graph of any Node project and count the amount of lines. Is it over 10? Okay, so now you know. If nobody really cares in the Node world, then chances are you or your teammates won't either. Idioms and best practices also fall in this category. Do you like the Pythonic way to write `list(map(x))`, or do you prefer `x.map().list()`? How about callbacks everywhere or prepending stuff with `async` and then wrapping more functions in `Promise.all()`? This might not sound like a big deal, but to me, the details do matter. Provided I _can_ choose the language, of course---most of the time, you'll have to work with what's already there.
---
For a natural language, many of these questions are organically answered and grown. But for programming languages, we can artificially construct something with a firm baseline and set of beliefs. Sure, there a whole slew of [constructed natural languages](https://en.wikipedia.org/wiki/Constructed_language), both a priori (artistic ones such as Klingon) and a posteriori such as Interlingua. The history of these languages is very fascinating. There, I now brewed a sixth question! Perhaps we could add a Q6: what's the _history_ behind the language? Why was there a need to create yet another language that didn't fit as a DSL in an existing one? Answering that question will usually say something about the purpose, culture, and design philosphy.
You see, it's never just a case of "I'll start investing in language `x` and be a good programmer really soon!". I even neglected to mention another important consideration: **fun**! Is it fun to write software in that language? Do you like it yourself? Why, or why not?
In the end, I tend to go with the recommendation of Andy and David: one language each year is more than enough. Seven in seven weeks is great to get a taste of each one and perhaps take a first jab at answering the above six questions, but you'll never embark on the journey of learning (let alone mastering) the language: there's simply too little time.
- 2019: C++11 and its ecosystem;
- 2020: ES6, keeping my Node/JS knowledge up to date, one `async` at a time;
- 2021: Kotlin and Go;
- 2022: Elixir.
See you on [ElixirConfEU](https://www.elixirconf.eu/) in June!

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long