Fortran has an interesting (and somewhat unusual) construct known as "arithmetic if". It looks something like this:
IF (arithmetic expression) label1, label2, label3
If the arithmetic expression evaluates to less than zero, control jumps to label1, equal to zero to label2, and greater than zero to label3. This construct is most often used to compare two numbers, in which case the arithmetic expression is of the form (x-y).
Arithmetic if fell out of favor with the advent of structured programming and is hardly ever used now. Since it is a disguised goto, all of the arguments against goto apply to arithmetic if as well. In addition, the syntax is considered by many modern programmers to be one of Fortran's particularly arcane constructs.
I don't think there is anything wrong with the idea of arithmetic if, however. Think of how often you write something like the following:
if (x < y) { ... } else if (x == y) { ... } else { ... }
This has the advantage of being structured and of using standard control flow constructs, but I don't think it is any more readable than the old arithmetic if. Here are some issues:
- Without reading the complex statement in its entirety, it is not clear that this is the equivalent of an arithmetic if.
- From a readability standpoint, there isn't a clear way to handle the final else statement. Consider for the moment integer comparisons, where <, ==, and > cover all the bases. You could write the final else as written above, in which case it stands out as different from the others in not having an if comparison (and because of this, you have to read the entire construct to know that this handles the > case). Or you could write the final else as "else if (x >y)", which at first glance may appear to be letting something slip through the cracks, as there is no final unqualified else.
- For floating point comparisons, these two solutions are not equivalent.
Besides readability, there are a couple other problems:
- There isn't a simple way to verify that there are no overlapping cases or missing cases. This concern is biggest for floating point comparisons, where there exist several not mutually exclusive comparison predicates.
- This construct is particularly well suited to optimization. However, as an if...else if...else construct, the optimizer needs to look harder to find it.
I want to resurrect arithmetic if in a more readable form. The most reasonable approach seems to be a special type of switch statement:
switch (x ? y)
{
case <:
...
case ==:
...
case >:
...
}
(I apologize for the spacing; it appears this blog software is not very friendly to code)
This approach has the additional benefit of being able to take advantage of the default case policy of the language (I personally like D's implicit assert on default for missing default statements).
This construct could be more flexible than the example I have given above. There is no reason, for example, that there couldn't be "case <=", "case !=", "case unordered", etc., as long as the cases don't overlap.