Programming Corner from Newsletter 33


May 15, 1990 ; Icon Version 8

Trivia

Last time we asked for the shortest complete Icon program that will compile and execute without error.

Several persons suggested
procedure main()
end

That seems logical, but the correct answer is
record main()

The resulting record constructor provides the main "procedure" that every Icon program needs to execute. When this program runs, it creates a single record of type main and then terminates normally.

Scope

We recently received a program via e-mail from a programmer who had installed Version 8 of Icon and thought he'd found a ghastly bug in Version 8 or in his C compiler. We had a few bad moments, since the program in question produced very different results when run under Versions 7.5 and 8. However, the difference was so marked that we had some faith that nothing so radically wrong could have gotten by our Version 8 testing process. On the other hand, there wasn't anything obvious in the program that would account for the difference in results between Version 7.5 and 8. When we did find the problem, we were reminded to practice what we preach.
Here's a simplified version of the procedure that caused the problem:
procedure print(x)
   args := x
   every i := 1 to *args do
   if type(args) == "list" then print(args[i])
   else write(image(args))
end

This procedure looks innocuous -- why should it behave differently in Versions 7.5 and 8?
The problem is that Version 8 of Icon has a new function, args(p). The names of functions are global. Since there is no declaration for args in the procedure print(), args is global in Version 8. In Version 7.5, however, there is no args() functions and args defaults to local in this procedure, which was what was intended. Since args is global in Version 8, the recursive call of print() changes the value of args in the middle of the loop.

So much for "upward compatibility".

Not having to declare local identifiers is a convenience, but a dangerous one, as this case clearly shows. The moral is, of course, to play it safe and declare all local identifiers. And if you have a program with a puzzling bug, check for local declarations and add them if they are missing before spending a lot of time trying to find the precise location of the problem.

You might fault us for using the name args for a function, since that name certainly is appealing for use as a program identifier. On the other hand, it's handy to have reasonable mnemonics for functions and the problem cannot be completely avoided in any case. Incidentally, another name that sometimes causes this problem is tab.

You might also question Icon's handling of default scoping. It's too late to change it now, however.

Icon home page