|From:||Louis de Forcrand|
|Subject:||Re: [Bug-apl] Supporting negative ranks for ⍤ operator|
|Date:||Sat, 7 May 2016 00:03:18 +0200|
|Sorry for answering so late.|
I'm basing everything I say on rank as it's interpreted in J.
The rank of an array is the number of dimensions it has.
A scalar has rank 0, a vector 1, matrix 2, cube 3, etc.
If an array has the shape 3 1 4 1 5 9, then it can be
"decomposed" into a frame and cells: it can be a rank-0
frame of rank-6 cells (6-cells), and the total shape of the
array is the shape of the frame appended to the shape
of the cells, so '',3 1 4 1 5 9 or simply 3 1 4 1 5 9.
If we now take each scalar, we have a rank-6 frame
(shape 3 1 4 1 5 9) of 0-cells, and the total shape is still
3 1 4 1 5 9 , '' which is 3 1 4 1 5 9.
Now on to the more interesting part: rank 1 cells. Each will
have a shape of 9, the frame will have a shape of
3 1 4 1 5, and the total will still remain 3 1 4 1 5 9.
2-cells, 3 1 4 1 shape of frame, 5 9 shape of cells.
3-cells, 3 1 4 shape of frame, 1 5 9 shape of cells.
4-cells, 3 1 shape of frame, 4 1 5 9 shape of cells.
5-cells, 3 shape of frame, 1 4 1 5 9 shape of cells.
Now for negative ranks: formally, the shape (soc) of a k-cell of
an array M is
while the shape (sof) of the frame is
The same holds for negative ranks. When you assign a positive
rank to a verb, you're basically placing an upper limit on the rank
of the arrays that are fed into it (as higher-rank arrays will be
"cut up" into smaller ones). In other words, you're choosing the
rank of the cells. With a negative rank, you're choosing the rank
of the frame. Some simple operations that aren't so simple to
execute without negative rank would be monadic ⍉⍤¯1 or ⍉⍤¯2,
or, of more use, ⊂⍤¯1 or ⊂⍤¯2.
Then again, this is how it works in J. Apparently ISO APL treats
negative ranks exactly like their positive counterparts, but I don't
really see any use or error-catching advantage in that. In addition,
negative rank can be pretty useful sometimes.
On the other hand, negative rank is indispensable in J, because
there is no axis operator. To do (with ⎕IO←0):
⊂ <—> ⍉ ⊂⍤1 ⍉
⊂ <—> ⍉⍤¯1 ⊂⍤1 ⍉⍤¯1
⊂[N] <—> ⍉⍤(-N) ⊂⍤1 ⍉⍤(-N) ⍝ except for ⊂
In APL, not only is there already an axis operator, but there
are some features that rank exploits that aren't present in APL.
For example, in J, u"1 _ (or u⍤1 ∞) will do a sort of outer product,
where each vector in ⍺ will be matched up with a copy of all of
⍵, but I don't think APL automatically duplicates arrays to match
rank unless it's duplicating a scalar:
1+3 3⍴⍳9 works in APL, but 1 2 3+3 3⍴⍳9 doesn't;
both work in J, and 1 is added to the first line
of the matrix, 2 to the second, and 3 to the third.
APL doesn't have a way to express infinite rank as was shown above
either. In the end it might just be better to stick with the standard, as
it probably is more adapted to the rest of APL.
|[Prev in Thread]||Current Thread||[Next in Thread]|