They exist throughout the universe, from the smallest seashells to the largest galaxies.
They exist in mathematics and arts.
The neolithic monument of Newgrange, Ireland, is 5,200 years old—older than Stonehenge or the Egyptian pyramids. One remarkable feature is the big entrance stone that carries beautiful spiral engravings.
If you enjoyed the book "The Good Spy Guide: Secret Messages" by Falcon Travis and Judy Hindley in your youth, then (a) you are probably as old as I am, and (b) have learned, and maybe even used, the spiral cipher for encrypting and decrypting secret messages.
I don't know whether the designers of the C language knew this book, too, or whether they unintentionally have introduced spirals into the language. But they do exist, and they play a vital role in reading declarations.
On 1994-05-06, exactly 29 years before this article was published, David Anderson posted an elaborate explanation of how to read C declarations to the Usenet forum
comp.lang.c. The gist of David's post was a technique called the "Clockwise/Spiral Rule" that enables the avid C developer to decipher C declarations of any complexity.
Here is a first, simple example, right from the original post. Consider this C declaration:
What does this line declare? To answer this, you start at the name of the declared entity and spiral clockwise outwards, like so:
+-------+ | +-+ | | ^ | | char *str; ^ ^ | | | +---+ | +-----------+
(All spiral diagrams are taken from the original post.)
So you start at
str, move on to
 (an array of length 10), further on to
* (denoting a pointer type), and finally to
Now you know that "
str is an array of length 10 of pointers to
This rule is genius! No C declaration can hide its true meaning anymore!
Occasionally, you'd need to read a spiral inside a spiral, as in this example:
void (*signal(int, void (*fp)(int)))(int);
signal, you quickly discover (by following the spiral rule) that this is a function with an
int as the first parameter, and some gibberish as the second parameter. Here, you can start a second spiral starting at
fp and decipher that parameter before returning to the main spiral.
Your journey through the declaration looks like this:
+-----------------------------+ | +---+ | | +---+ |+-+| | | ^ | |^ || | void (*signal(int, void (*fp)(int)))(int); ^ ^ | ^ ^ || | | +------+ | +--+| | | +--------+ | +----------------------------------+
(Find the complete explanation in the original post, Example #3. I have skipped Example #2 for brevity.)
At this point, you can tell that "
signal is a function that passes an
int and a pointer to a function named
fp passing an
int returning nothing and returns a pointer to a function passing an
int returning nothing."
Piece of cake!
Unfortunately, the designers of Go did not carry that gem of language design culture over to their language.
Go is known as The Boring Language, and so are its declarations.
Here is the rule you have to follow: Read them from left to right.
If you don't believe me, here is the C example #1 in Go syntax. The letters in the comment mark the individual parts of the declaration:
var str *string //a b c de
Read: "A variable (a) named
str (b) that is an array of length 10 (c) of type pointer (d) to string (e)."
Do not expect anything more exciting for the Go version of the C example #3:
func signal(sig int, fp *func(int)) *func(int) // a b c d e fg h ij k
Read: "A function (a) named
signal (b) with a parameter named
sig (c) of type
int (d) and a second parameter
fp (e) of type 'pointer (f) to a function (g) that takes an
int (h) and no return value' that returns a pointer (i) to a function (j) taking an
int (k) and returning nothing.
Again, the declaration reads straight from left to right. No exceptions.
It's all about readability
Yes, I know. Go declarations are not nearly as exciting as C declarations.
But the Go designers did not accidentally derive from the good ol' C style. Turning the declarations around by 108 degrees (
n int instead of
int n) makes all the difference in reading and understanding a declaration with confidence.
Go is, among other features, a language made for readability. Code is much more often read than written. Hence, a productivity-oriented programming language must avoid at all cost being a write-only language that encourages clever coding at the expense of readability.
The Go designers have done an outstanding job in this regard.
And now pull the plug of your kitchen sink and watch the water spiral out.
Disclaimer: No AI was harmed in the making of this article.
Categories: The Language