arrays are records are tuples

8.19: adda/dstr/array and record syntax as modes of access:
if ( x.y ) and ( x#y ) are both valid
regardless of whether x is defined as an array or record;
this ignores an idiom where
arrays represent lists of items,
while records represent items with named parts;
. well, my way lets you do it both ways,
but it should be admitted that the writer's freedom
is inevitably the reader's headache .

adda/dstr/array vs record precedence:
. if you have x#y.z
does it mean x#(y.z) or x#(y).z ?
my first impression is that y.z is the tightest binding;
ie, it means x#(y.z);
also, (x#(y) = x#y) only when y is an atom,
and you could argue that y.z is not an atom:
it's a sort of address-addition operation; [11.16:
but, of course, that would be a stretch!
it's more intuitively seen as a style of atom naming .
. finally, consider how functions and arrays
should be similar;
( f x.y ) should be seen as a variant of
( a# x.y ); therefore, the parsing is ( a#(x.y) ). ]
. x.y#z is unambiguous: x has component y,
which is an array taking parameter z;
ie, it's parsed as ( (x.y)#z ).

8.20: adda/dstr/arrays are a species of record.type:
. an array is generating a list of component names,
and then declaring them all to be the same type .
. records are a generalization of this,
where a generated list of components
can have a variety of types .
. in fact, fully-oop arrays are actually records;
because, they often have a variety of types .
. arrays are parameterized types,
and records can be parameterized too
. here's a syntax for allowing a record
to describe parts of itself the way arrays do:
reca(n.int).type: ( a.t1, b.t2, #(0..n).t3 );
-- now x = (a:..., b:..., 0:..., 1:..., 2:..., 3:... ).