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

Reply via email to