All ya gotta do…

My older son (also a programmer) called my attention to a bit of JavaScript trivia that illustrates nicely the consequences of subtle interactions among independent, well-intentioned decisions (console transcripts courtesy of node.js).

Everyone agrees that programming languages should give the programmer more control, convenience, and flexibility, right? So all of the following sound like good ideas, don’t they?

Everyone knows that programs should not blow up.

(This is important, among other reasons, because users frequently provide silly input.) Operators should do something reasonable in almost every conceivable situation, and just let the programmer write tests for silly things. Therefore, given

a = "my dog has fleas"

we want the following results:

> a
'my dog has fleas'
> a.substr(0, 2)
'my'
> a.substr(3, 3)
'dog'
> a.substr(42, 7)
''

because the programmer can always check for out-of-bounds results:

> a.length
16
> a.substr(42, 7).length
0

and given

b = [2, 4, 6, 8]

we want these results:

> b
[ 2, 4, 6, 8 ]
> b[0]
2
> b[3]
8
> b[5]
undefined

because the programmer can always check:

> b.length
4
> (typeof b[5]) === "undefined"
true

Everyone knows that floating point arithmetic can overflow.

(Dividing a positive number by zero is a special case of that general situation.) Instead of blowing up the program, let’s just return a unique value that we can check for:

> isFinite(1 / 2)
true
> isFinite(1 / 0)
false

and, of course, an overflow must absorb all subsequent computations:

> 1 / 0
Infinity
> (1 / 0) + 4
Infinity
> ((1 / 0) + 4) * 10
Infinity
> (((1 / 0) + 4) * 10) - 5
Infinity
> ((((1 / 0) + 4) * 10) - 5) / 2
Infinity

Everyone knows that overloaded operators promote familiarity and economy of notation.

Common mathematical and programming practice lead us to expect the following:

> 2 + 3
5
> 2.1 + 3.1
5.2
> "2" + "3"
'23'

Everyone knows that we need automatic type conversions.

It is convenient to have “narrower” values converted automatically to “wider” types when evaluating expressions. So clearly we need this kind of “widening”:

> 2 + 3
5
> 2.1 + 3.1
5.2
> 2 + 3.1
5.1
> 2.1 + 3
5.1

Now that we’ve established that, the obvious next step is to support this kind of “widening” as well:

> 2 + 3
5
> "2" + "3"
'23'
> 2 + "3"
'23'
> "2" + 3
'23'

Everyone knows that we need controllable conversion of strings to numbers.

In addition to:

> parseInt("123")
123

programmers need to deal with binary:

> parseInt("1101", 2)
13

and other computer-oriented bases:

> parseInt("123", 8)
83
> parseInt("123", 16)
291
> parseInt("123", 4)
27
> parseInt("ff", 16)
255

Since we can specify the base explicitly, we might as well support this:

> parseInt("123", 7)
66

or (for those of us who fondly remember the PDP-10):

> parseInt("ff", 36)
555

After all, programmers always know what they’re doing, and should always get exactly what they ask for.

> parseInt( 1 / 0, 19 )
18

No, I’m not hating on JavaScript. I’m observing that complex artifacts, such as programs, programming languages, political systems, and economies may not respond to “simple” decisions in the ways that we expect. And a pithy statement that encourages reflection and self-restraint

Don’t repeat yourself.

is very different from simplistic responses to non-simple situations.

You don’t need static typing; just write tests.

or

If you want to eliminate run-time problems, just used a statically-typed language.

or even

These problems are the fault of the other party; just vote for my candidate.


The title comes from a co-worker on a large project a few years ago. The effort offered several design challenges, and it seemed all to easy for well-meaning participants (and non-participants) to propose simplistic solutions. After a while, his standard response was to say with a grin, “All ya gotta do…

Server-side use aside, node.js includes a local JavaScript interpreter and console that offers a convenient tool for learning and experimentation. The e-book What Is Node? (free as of this writing)
provides a fast-paced introduction, while Node: Up and Running: Scalable Server-Side Code with JavaScript and Node.js in Action
give more detailed coverage.

There’s an Easter-egg link in the article to Dijkstra’s famous Turing Award lecture entitled The Humble Programmer. Despite its length (slightly longer than a typical blog post) and serious tone, it’s worth the time. Care in the construction of our programs is still appropriate, whether we call it “software craftsmanship”, “joint application development”, or “pragmatic programming”.

Even though the title phrase became an abused cliche, Structured Programming (A.P.I.C. studies in data processing, no. 8)
is a classic in our field. Although we have (some) nicer tools at our disposal, a careful reading shows how little the fundamental challenges of programming have changed in 40 years. A collection of Dijkstra’s essays, Selected Writings on Computing: A Personal Perspective paints a broader picture of the issues that have challenged us in roughly that same time frame. It is a mix of technical articles, notes on the computing culture of the day, and amusing (but pointed) parables.

Trackbacks are closed, but you can post a comment.

Leave a comment