[QUOTE="Lew said:
long[] endOfYearBalancesThisDecade = new long[2001:2010];
(Imaginary syntax, of course.)
Patricia said:
This is an interesting illustration of the merits of defining
arrays with meaningful index ranges.
With zero based index ranges, all we could have told from the
declaration is whether the programmer thought there were ten years
in this decade or not. The issue of which years are in the decade
would only have arisen from comments or from looking at some of the
code using the array.
I can't tell if your argument supports varying index ranges or zero-based
ones.
The term "decade" means an arbitrary span of ten years. The
definition of "decade" for a particular organization or project
depends on the business rules or domain rules for that organization
or project. Things like when a fiscal year starts affect the
decision. Mergers and acquisitions, refactoring of business
processes, and other factors can cause the definition to change
withing the lifetime of the software system.
Defining an array to have its decade start with a given year, say,
limits its flexibility compared to defining only the length of the
array and letting domain-centric logic determine which years belong
in it. I imagine that in the normal case it would be better to store
the start year of a "decade" as data rather than to hard-code it into
the source.[/QUOTE]
I think Patricia meant that explicit index ranges might offer improved
expressiveness. Your valid points address whether the given values
express a particular program's intent. Of course, both are essential to
evaluating correctness.
In the following examples, I compare Java to Ada not to express a
preference but merely for reference. Java strings are indexed from 0,
slightly complicating the API invariants with -1; Ada's most primitive
String type are indexed from 1, with arguably simpler invariants.
Similarly, Java arrays representing matrices are indexed from 0. In
Ada, a polynomial's coefficient array may start with index 0, while the
corresponding array of roots may start with index 1. The Ada library
support for matrices is generic, so any suitable discrete type may be
used as the index.
As another example, an enumerated type in Ada may serve as an array
index:
type Season is (Winter, Spring, Summer, Fall);
S : Season;
A : array(Season) of Natural := (others => 0);
for S in Suit'Range loop
-- only valid values of S are possible
A(S) := 1;
end loop;
Similarly, in Java, a program may safely traverse the values of an enum:
enum Season { WINTER, SPRING, SUMMER, FALL }
static int[] a = new int[Season.values().length];
public static void main(String[] args) {
for (Season season : Season.values()) {
// only valid values of season are possible
a[season.ordinal()] = 1;
}
}
Would there be any value to allowing a[season]? An EnumSet seems more
apt.
Along the same lines, Wojtek asks "So how do you loop through this?
Define constants for min/max?" In languages that support it, the array
bounds are typically defined by the declaration itself. In Java, the
for-each construct could use the explicit bounds for iteration, and the
usual array bounds checking would apply to normal indexing.