This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Proposed syntax for matrix element access and slicing. =head1 VERSION Maintainer: Buddha Buck <[EMAIL PROTECTED]> Date: 29 August 2000 Last Modified: 14 September 2000 Mailing List: [EMAIL PROTECTED] Number: 169 Version: 2 Status: Withdrawn Superceded By: RFC 204, RFC 205, RFC 206, RFC 207 =head1 CHANGES This RFC is withdrawn in favor of RFCs 202-207. Most of the ideas presented in this RFC have been incorporated in RFC 205 (New operator ; for creating array slices), RFC 206 (@#arr for getting the dimensions of an array), and RFC 207 (Efficient Array Loops). The combination of RFC 205 and RFC 204 create a more flexible array index technique than presented in this RFC. The main body of this RFC is left here as a historical record. =head1 ABSTRACT I propose the use of ';' as a separator for index terms when accessing multi-dimensional arrays (matrices). The syntax "$matrix[$w;$x;$y;$z];" is clearer and more flexible than other proposed alternatives. The flexibility is mainly in the possibility of a robust slicing syntax. Although I know of no RFC's that recommend the implementation of matrices, I expect such a proposal to be made, and this RFC does not make such a suggestion. =head1 DESCRIPTION Several suggestions have been made for matrix element accessors, including: $matrix[$x][$y][$z] # aka "(Lo)*L" notation ( (lists of)* lists) $matrix[$x,$y,$z] # aka "[,,]" notation $matrix{"$x,$y,$z"} # aka hash notation All three of these have problems. The (Lo)*L notation either requires matrices be (lists of)* lists, or uses the same syntax for both matrices and (lists of)* lists. The hash notation has the same confusion, but with hashes. The [,,] notation is too similar to the existing syntax for array slices. None of them allow for convenient matrix slicing. Using $matrix[$i;$j;$k;$l] has the advantage that it is dissimilar from exising syntax, thus minimizing confusion with pre-existing data structures, and it provides a clean separation of indices, allowing for a flexible slice notation. =head2 Matrix Element Access. Matrix elements should be accessed as normal arrays, but using ";" to separate the indices: my @matrix; $matrix[1;2;3;4] = 5; sub tensor2mul { my @tensor1 = @{shift @_}; my @tensor2 = @{shift @_}; my @tensor3; for $i (0..3) { for $j (0..3) { for $k (0..3) { for $l (0..3) { $tensor3[$i;$j;$k;$l] = $tensor1[$i;$j] * $tensor2[$k;$l]; } } } } return @tensor3; } Currently, ';' is only used for statement separators and as term separators in for(;;) loops. This new proposed use should not be a problem for the parser or programmers to understand in this context. =head2 Matrix Slices Because the indices are separate, array slice notation can easily be used for the individual indices. #exlude row $j and column $k, as if taking a determinant. @submatrix = @matrix[0..$j-1,$j+1..$n;0..$k-1,$k+1..$n]; While that should work obviously enough, a more flexible syntax would be nice: # leave index blank for "all" # or use unterminated ".." @row = @matrix[1;]; # @row = @matrix[1;..]; @col = @matrix[;1]; # @col = @matrix[..;1]; @swaprow = @matrix[1,0,2..$n;] # Use ^var to get more complicated slices @diagonal = @matrix[^i;^i]; @rdiagonal = @matrix[^i;$n-$i]; @uptriangle = @matrix[^i;0..$i]; @lowtriangle = @matrix[^i;$i..$#]; # These would be nice, but probably not feasable @trans[^i;^j] = @matrix[^j;^i]; @tensor3[^i;^j;^k;^l] = @tensor1[^i;^j] * @tensor2[^k;^l]; $dotproduct = reduce ^1+^2 , 0, a[^_] * b[^_]; Those above would work if the ^vars would scope across all indices in the statement, not just one. # use $# to get maximum val for index sub lowtriangle { @matrix = @{ shift @_ }; return @matrix[^i;^i..$#]; # works for all 2-d matrices. } Matrices of more than two dimensions should be handled similarly: # Slice through middle of cube perpendicular to main diagonal @slice = @matrix[^i;^j;^i-^j]; The use of the ^var syntax is analogous to the use of ^placeholder syntax in Damian Conway's HOF RFC. =head2 Computing the size of matrices I'd propose that, analogous to the $#array notation for revealing the upper index of @array, @#matrix return the analogous list: my @matrix $matrix[2;2;2] = 1; @sizes = @#matrix; # @sizes == (2,2,2) $numdim = @#matrix; # array in scaler context. =head2 Unresolved issue -- variable dimensionality Right now, the syntax above hardcodes the dimension of a matrix in the index list. This does not allow you to write programs which manipulate $n-dimensional matrices, where $n is computed at run-time. This is unfortunate, and I'd like to hear suggestions on how to deal with that issue. One possible mechanism would be to allow @k = @matrix[$n;]; to always assign to @k a matrix of one less dimension that @matrix, regardless of the original dimensionality, with the exception that @array[$n;] will return a singleton list rather than a 0-dimension matrix (which should by rights be a scalar). How that should generalize is not clear. =head2 Unresolved issue -- ^var slices and HOF Damian Conway suggested a HOF syntax which used ^var as a placeholder. The "reduce" example above shows how confusing using both HOF and ^var slices in the same expression can be. Originally, I thought this wouldn't be a problem because closures are not allowed as array indices, so @a[^i;^j] would be unambiguous. But this precludes being able to say: my &closure = $matrix[^_;^_]; # closure(1,2) == $matrix[1;2] my &c2 = closure(^_,5) ; c2(4) == $matrix[4;5] I think both functionalities are powerful and useful. I would appreciate how to get both of them unambiguously and cleanly. =head1 IMPLEMENTATION Using ; as a indices separator should cause no serious problems of implementation. The use of ^var indices could, in a reference implementation, be syntactic sugar for something like: @matrix[^i;^j;^k;^k] ==> do { my @result; my ($i,$j,$k); my @indices = @#matrix; for $i (0..$indices[0]) { for $j (0..$indices[1]) { for $k (0..$indices[2] { $result[$i;$j;$k] = $matrix[$i,$j,$k,$k]; } } } @result; } It should be noted that the matrix slice operations are likely to be inherently O(k), where k is the number of dimensions indexed over. =head1 REFERENCES RFC 24: "Higher Order Functions" RFC 204: "Arrays: Use list references for multidimensional array access" RFC 205: "Arrays: New operator ';' for creating array slices" RFC 206: "Arrays: @#arr for getting the dimensions of an array"