Asymmetric Bounds, Part 1: What Are They?
C and C++ programmers usually express ranges asymmetrically, by writing the first element and one past the last element in the range. For example, if we have a 10-element array,
then we might initialize the elements by writing
for (int i = 0; i != 10; ++i) x[i] = i;
We might have written
i < 10 instead of
i != 10, and both of these forms are widely used. However, even though it is equally valid to write
i <= 9, such usage is generally considered weird and counterstylistic for C++.
The difference between writing
i <= 9 and writing either of the other forms is that
i <= 9 specifies
9 as an inclusive upper bound. The first two forms give exclusive upper bounds — bounds that the variable
i never takes on inside the loop. We talk about the bounds of this loop as being symmetric because the variable
i takes on the value
0 for the first trip through the loop, as well as taking on the value
9 the last time through the loop. If we write the loop with
10 as its upper bound, then
i never takes on that value inside the loop body, even though it still has the value
0 the first time through the loop. Accordingly, we refer to the bounds of such a loop as asymmetric.
Asymmetric bounds are not universal. Fortran, the first programming language that I learned, has array bounds that (normally) start from 1 rather than from 0, so the Fortran code that corresponds to the C++ example above might look like this:
integer x(10) do 1 i = 1, 10 1 x(i) = i
Like its C++ counterpart, the declaration of
x says that it has 10 elements. Unlike C++, Fortran numbers those elements
10. Accordingly, the first value that
i takes on during the loop is
1 and the last value is
10. The bounds in Fortran's loops are symmetric. Moreover, this symmetry is written into the Fortran language as part of the definition of how a
do statement behaves.
Although Fortran was among the earliest programming languages, the weight of history was not enough to convince Fortran's successors to express loop bounds in the same way. Moreover, although Fortran and its contemporaries used 1 as the starting point for array indices, most more recent languages start counting arrays from 0. Evidently, there are advantages to counting from 0 that are not apparent at first.
What is also not apparent is that once a language designer decides to count from 0, asymmetric bounds become much more attractive. I'll start exploring the reasons for this attraction next week.