RFC 204 (v1) Array: Use list reference for multidimensional array access

[email protected] (Perl6 RFC Librarian)
Newsgroups perl.perl6.announce.rfc,perl.perl6.language.data
Message-ID <[email protected]>
This and other RFCs are available on the web at
  http://dev.perl.org/rfc/

=head1 TITLE

Array: Use list reference for multidimensional array access

=head1 VERSION

  Maintainer: Buddha Buck <[email protected]>
  Date: 8 September 2000
  Mailing List: [email protected]
  Number: 204
  Version: 1
  Status: Developing

=head1 ABSTRACT

This RFC proposes that array indexing syntax be extended to use references
to integer lists as indices for multidimensional arrays.

=head1 DESCRIPTION

Currently in Perl5, arrays can be indexed by a single integer, or sliced
by a list of integers. This notation is sufficient and convenient for one
dimensional arrays (like Perl5 has), but is problematic for
multidimensional arrays.

Because n-dimensional arrays have more than one dimension, their indices
are not simple integers, but rather n-tuples of integers. While lists are
natural Perl representations of n-tuples, they present problems when used
as multidimensional array indices:

=over 4

=item *

It is ambiguous if @a[@point1,@point2] is a 2-element slice of a
multidimensional array, or if it is a multi-element slice of a single
dimensional array.

=item *

Although $a[@point] is not as ambiguous (it is currently a syntax error),
it still could be confusing, especially when seeing both $a[1,3,4] and
@b[1,2,4].

=item *

It is inconvenient use a list of n-dimensional indices for a slice. By
Perl syntax, such a list would have to be a list of lists, whereas
currently Perl only allows lists of scalers.

=back

A solution to these problems is to encapsulate a list of integers into a
scaler, such as using a list reference. By using list references for
indices (and lists of list references for slices), the multidimensional
case is similar to the unidimensional case: $a[$scaler] would access a
single element, @a[@list] would access a slice.

This would solve the problems above:

=over 4

=item *

@a[$point1,$point2] is no longer ambiguous, but obviously a 2-element
slice from the array @a. The dimensionality of @a is not an issue with
this syntax.

=item *

Multidimensional and unidimensional array access both use $a[$point], so
$a[1,3,4] will not be seen. Instead, any confusion would have to be
between $a[[1,3,4]] and @b[1,2,4]. Since $a[[1,3,4]] is an array indexed
by a single scaler value (the listref [1,3,4]), whereas @b[1,2,4] is an
array indexed by a list of scaler values explains clearly (and possibly
redundantly) the use of $ and @ as prefixes.

=item *

List of lists are naturally stored as list of scalar references to lists.
As such, the natural representation of lists of lists ties in well with
taking multidimensional array slices:

for my $t (1..10) { push @points,[getx($t),gety($t),getz($t)]; } $point =
$points[3];

@array[@points] = 1 x @points; $array[$point] = 0;

=back

This proposed syntax extends to unidimensional arrays as well. $a[[$b]]
being an alternative way of saying $a[$b], when $b is an integer. $a[[]]
would return the (unique) value of the zero-dimensional array @a, not the
value of the scaler $a.

A listref used as an index must have the same or lower cardinality as the
dimensionality of the array (if the array is declared with ':bounds'-- see
RFC 203), and must have elements within the declared or implied bounds of
the array indexed.

my int @array :bounds(3,3,3); $array[[0,1,2]] = 5; # OK, within bounds.
$array[[0,1,4]] = 5; # error, out of bounds $array[[1,2,1,2]] = 5; #
error, out of bounds, too many dimensions

If the cardinality (c) of the index is lower than the dimensions (d) of
the array, then the innermost (n-d) dimensions of the array are returned:

my int @array :bounds(3,3,3); $array[[1,2]] = (1,2,3,4); # Sets the line
at (1,2) to (1,2,3,4)

When a listref is used to index a list of lists, the returned list
reference is automatically dereferenced:

my @array( [0,1],
           [1,2]);
my @a = @array[[0]]; # Returns (0,1), _not_ [0,1]

The ; operator (defined in RFC 205) is designed to return lists of
list refs, to make for efficient indexing and slicing of
multidimensional arrays.

@points = ((1,2);(3,4);5); @points = ([1,3,5],[1,4,5],[2,3,5],[2,4,5])
@array[@points]= 5 x @points;

=head1 IMPLEMENTATION

Implementation of this feature is dependent on the underlying
implementation of multidimensional arrays. Other than that, it is a
straightforward enhancement of the semantics of list indexing.

=head1 REFERENCES

RFC 202: Overview of multidimensional array RFCs

RFC 203: Notation for declaring and creating arrays

RFC 205: New operator ';' for creating array slices.

=head1 ACKNOWLEDGEMENTS

Jeremy Howard: Suggested listref indexing
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.