Programming idioms

Introduction

Since programming languages are used mainly to convey ideas to other people, and only secondarily to convey code to the compiler, programming languages work much like ordinary languages such as English or French.

Like ordinary languages, programming languages have idioms, and practitioner of programming languages recognize usage the way linguists do.

Let us take an example. In English you say "I am hungry". You can say the equivalent in French (je suis affamé), but people just don't. It is a grammatically correct statement that is never used. It is not a French idiom. Instead in French you say "j'ai faim", which means "I have hunger", which in English is a grammatically correct phrase that nobody uses. "I have hunger" is not an English idiom. Writing English or French is not only a question of producing grammatically correct phrases, but also to apply correct usage and to use the correct idioms.

Here is a grammatically correct phrase in C:

  for(i = 1; i <= n; i = i + 1)
    a[i] = 0;
While this looks like C, it is really Fortran usage with C syntax; sort of like "I have hunger". Arrays are zero-based in C, and nobody writes i = i + 1 in C. Here is the idiomatic version:
  for(i = 0; i < n; i++)
    a[i] = 0;

Programming is a communication activity

There is widespread belief that the activity that we call "programming" is just a matter of producing grammatically correct code (i.e. according to the language definition) that also produces the right result. Nothing can be further from the truth.

In fact, the main purpose of code is for communication with the maintainer, i.e. the person who one day in the future must read, understand, and modify the code, perhaps in order to add new functionality. The widespread belief cited above completely ignores the existence of a reader of the code.

The fact that programming is a communication activity makes it much more similar to the activity of writing prose than to, say, mathematics or logic. In all such communication activity, the use of the language plays an important rôle. Communication is made possible by the shared culture of the people involved, and by shared usage and idioms.

If programming is similar in spirit to writing prose, then most teaching programs are making a big mistake in the way programming is taught. In order to be a fluent writer, one also must be a fluent reader. Any teaching program that only emphasizes writing programs and not reading programs would be similar to a course for writing novels in which the students were not required to be able to read and understand novels.

Some more C idioms

In this section, we examine some more simple C idioms that the beginner might find hard to understand, and that even some experienced programmers find hard to read. We are convinced that there are few programming idioms that are intrinsically hard to read. Instead we think there are only differences in how well the human reader is familiar with those idioms.

Using pointers to fields and variables

In the chapter on unsorted lists, we discussed using the ability in C to point to variables and fields of structures (as opposed to the entire structure). This possibility gives rise to programming idioms for traversing lists that do not require trailing pointers in situations where other languages might.

Lazy logical operations

The fact that logical operations such as || and && evaluate their arguments from left to right, and only as many as necessary to determine the result of the operation, gives rise to programming idioms that are not possible in languages such as Pascal, where all arguments are always evaluated.

For instance, in the chapter on unsorted lists, we used the following loop termination condition:

  *llp && !equal((*llp) -> element, element); 
where the second argument of the && operator would fail if the value of the first argument were false.

Pointers to functions

The C language allows for pointers to functions to be stored in static or automatic variables, in arrays, and in structures. We used this possibility in the chapter on unsorted lists to avoid having to pass the equality function to each operation. Instead we passed it only to the creation function, which stored it in the structure representing the abstract data type.

Conditional expression

The C language has a ternary expression (using the two operators ? and :) that can participate in many C idioms, but that are not idioms in other languages without this expression. For instance, the following is not a C idiom:
  if(a == 4)
    b = 5;
  else
    b = a - 1;
The corresponding C idiom is instead:
  b = a == 4 ? 5 : a - 1;
which is both shorter and idiomatic C. Similarly, the following is not a C idiom:
  if(a == 4)
    return 5;
  else
    return a - 1;
The corresponding C idiom is instead:
  return a == 4 ? 5 : a - 1;
which again is shorter and idiomatic C.

Nonlocal gotos

The C language has two instructions setjmp and longjmp that are missing from other languages. These instructions can be used to handle exceptional situations. Thus, it is not idiomatic C to use return codes to indicate whether exceptional situations occurred or not. This is not idiomatic C:
  static int
  myfun(int arg)
  {
    ...
    fd = open(filename);
    if(fd == -1)
      return CANNOT_OPEN;
    /* normal processing */
    return OK;
  }
This is an idiomatic C version of the above:
  static void
  myfun(int arg)
  {
    ...
    fd = open(filename);
    if(fd == -1)
      longjmp(jmp_buf);
    /* normal processing */
  }