Magic, or the lack thereof
“Any sufficiently advanced technology is indistinguishable from magic.”
– Artur C. Clarke
Go is often called a non-magical language.
But what does “non-magical” exactly mean?
The magic in programming languages
For years, I have used to point people to this rant in the middle of Joel Spolsky's article “Make Wrong Code Look Wrong,” to give them an idea of magic vs. non-magic code. (If the link does to show the highlight right away, search for “language features that hide things” in that article.)
Now, thanks to Jeremy Bowers, aka Jerf, I have a more general and more nuanced take on the magical aspect of programming languages to refer to:
A Definition of Magic in Programming Languages
(Fun fact: Jerf's article goes back to a 2017 post on HackerNews that is probably the first time Go was labelled non-magical. Even Peter Burgon's classic article A theory of modern Go that probably made the notion of Go as a non-magical language popular (don't hold me accountable on this postulate) links back to the HN post.)
In his article, Jerf unfolds several ways in which language features can be considered magical, and he concludes that magic in code is not inherently good or bad, but the benefit that a magic feature adds must be carefully weighed against the cost it adds. (Where cost mostly equals to the added mental burden of deciphering the effects of code using, or being based on, a magic feature.)
Magic can be just fine
I don't have to look far to find an example of magic that was largely appreciated by its users. Years ago, my favorite scripting language was Perl. This language was full of magic. For example, consider the following tiny piece of Perl code:
while (<>) {
print if /perl/;
}
If you don't know Perl, it's almost impossible to deduce what this code does. The first magic involved here is the <>
operator (also called diamond operator). It's nothing more than a less-than and a greater-than symbol concatenated, but it does the bulk work of this code:
For every file name listed on the command line that invoked this script, <>
opens that file, assigns each line of this file to the default variable $_
(another piece of magic) and yields this variable to the loop body. If no file names are passed as arguments to the script, <>
reads from stdin. The print
line in the loop's body tests the content of $_
against a regular expression and prints the content of $_
if the regexp matches.
Easy, huh? ;-)
There is surely enough magic in those three lines to make everyone not familiar with Perl have a “WTF?!” moment. Yet, this pattern is so ubiquitous in Perl scripts that virtually every Perl programmer would recognize it at the blink of an eye. This is a rare example of magic without cost.
I think this Perl example shows the most prevalent benefit of magic language features: the avoidance of boilerplate code. Ater all, boilerplate code quickly becomes boring.
When magic becomes a burden
On the other hand, the biggest drawback of magic code features is that they tend to tuck away masses of logic behind innocent-looking symbols or keywords. It's the readers task to track down the origins of a magic piece of code, often having to dig through levels over levels of indirections.
I agree with Jerf that code magic is inherently neither good nor bad—see the Perl example above for an example of good magic. However, the more magical features a language provides, the more are the users of that language tempted to act “clever” (or so they think) and use all these features to their extreme, just to save a few keystrokes, or maybe even just to earn some bragging rights.
Nah.
I prefer verbosity to cleverness. Reading and comprehending code should be a straightforward and mostly linear task. I don't want to jump through hoops to understand what that plus sign in front of me actually does. I'd rather read through some extra amount of code if this enables me to quickly and unambiguously comprehend the code I'm reading.
Clear is better than clever.
– Go proverb