OK: before I submit a patch, let me make sure that I've got the
concepts straight:

"@x[0]" always means "the first element of the array"; "@x[-1]" always
means "the last element of the array"; "@x[*+0]" always means "the
first element after the end of the array"; "@x[*-1]" always means "the
first element before the beginning of the array".  That is, the
indices go:

..., *-3, *-2, *-1, 0, 1, 2, ..., -3, -2, -1, *+0, *+1, *+2, ...
                   ^                      ^
                   |                      |
                 first                   last

As well, a Whatever in square braces is treated as an array of the
valid positions; so @x[*] is equivalent to @x[0..-1].

If you want to use sparse indices and/or indices that begin somewhere
other than zero, access them using curly braces.  Consider an array
with valid indices ranging from -2 to +2: @x{-2} means "element -2",
which would be equivalent to @x[0]; @x{+2} means "element 2", which
would be equivalent to @x[-1].  Likewise, @x{0} is the same as @x[2],
@x{-3} is the same as @x[*-1], @x{+3} is the same as @x[*+0], and so
on.  If @y has a series of five indices that start at 1 and double
with each step, then @y{1} will be the same as @y[0]; @y{4} will be
the same as @y[2], and so on.

A Whatever in curly braces is treated as an array of the valid index
names; so @x{*} means @x{-2..+2}, and @y{*} means @y{1, 2, 4, 8, 16}.
Because it is treated as an array, individual index names can be
accessed by position: @x{*[0]} is a rather verbose way of saying
@x[0].  This lets you embed ordinal indices into slices involving
named indices.  Conversely, using *{...} inside square braces lets you
embed named indices into slices involving ordinal indices: @x[*{-2}]
is the same as @x{-2}.

Multidimensional arrays follow the above conventions for each of their
dimensions; so a single-splat provide a list of every index in a given
dimension, a 0 refers to the first index in that dimension, and so on.
A double-splat extends the concept to a multidimensional list that
handles an arbitrary number of dimensions at once.

--

Commentary: I find the sequence of ordinals outlined above to be a bit
messy, especially when you start using ranges of indices: you need to
make sure that @x[0..-1] dwims, that @x[-1..(*+0)] dwims, that
@x[(*-2)..(*+3)] dwims, and so on.  This is a potentially very ugly
process.  As well, the fact that @x[-1] doesn't refer to the element
immediately before @x[0] is awkward, as is the fact that @x[*-1]
doesn't refer to the element immediately before @x[*+0].  IMHO, it
would be cleaner to have @x[n] count forward and backward from the
front of the array, while @x[*+n] counts forward and backward from
just past the end of the array:

..., -3, -2, -1, 0, 1, 2, ..., *-3, *-2, *-1, *+0, *+1, *+2, ...
                ^                        ^
                 |                        |
               first                     last

So perl 5's "$x[-1]" would always translate to "@x[*-1]" in perl 6.
Always.  Likewise, "@x[+*]" would be the same as "@x[*+0]".  (In fact,
the semantics for "@x[*+n]" follows directly from the fact that an
array returns the count of its elements in scalar context.)  And
"@x[*]" would be the same as "@x[0..^*]" or "@x[0..(*-1)]".

You would lose one thing: the ability to select an open-ended Range of
elements.  For a five-element list, "@x[1..^*]" means "@x[1, 2, 3,
4]", not "@x[1, 2, 3, 4, 5, 6, 7, 8, ...]".

Technically, one could say "@x{+*}" to reference the index that
coincides with the number of indices; but it would only be useful in
specific cases, such as referencing the last element of a one-based
contiguous array.

--
Jonathan "Dataweaver" Lang

Reply via email to