I had a question for the team in our regular meeting on Wednesday, but it relied on an understanding on squad indexing, and nobody felt comfortable enough with ⌷
to answer my question.
I’ve since reach a conclusion and thought I’d share.
Squad indexing vs. Square bracket indexing
⎕←cube←?3 4 5⍴7
4 3 4 1 1
5 5 7 6 3
2 2 5 1 4
4 6 5 4 3
1 6 1 6 6
3 1 5 3 3
2 5 5 4 7
1 5 6 5 2
5 6 6 4 1
7 1 5 1 1
1 1 4 1 1
6 6 4 1 1
For a given 3-dimensional object, I can use square bracket indexing to retrieve the indices I want. I can even omit a dimension completely to receive all items in that dimension, i.e. here I am asking for the first plane, the second row, and all columns:
cube[1;2;]
5 5 7 6 3
In this example, you can do the same with squad indexing- just omit any indices for that axis:
1 2⌷cube
5 5 7 6 3
Square bracket indexing has a bit more of an advantage for some cases, though. If the axes you want are non-contiguous, you can ask for [x;;y]
. With squad indexing it’s not so simple. See the below example:
cube[1;;2]
3 5 2 6
1 ⍬ 2⌷cube
⍝ empty result
My thoughts were with [x;;y]
, ;; ←→ ⍬
, ⍬
representing an empty numeric array. This is not the case, however. As with typical indexing, the shape of the index is the shape of your result. Zilde is of shape 0 (⍬←→ 0⍴0
), and therefore I would get back a shape 0 result:
⍴1 ⍬ 2⌷cube
0
My question to the team was how would I perform an operation like this, similar to [x;;y]
?
Gilgamesh Athoraya has since told me the only way of performing this kind of indexing is to use axis specification:
1 2⌷[1 3]cube
3 5 2 6
I feel like there should be a way to do it using without specifying axis. Zilde may not be appropriate, but it was my immediate go-to answer. In fact, what we’re after is not an empty array, but an array whose shape is that of the actual object- identity (⊢
) would achieve something like this. There is a slight issue with using identity, though:
1 ⊢ 2⌷cube
Here, right tack will be used dyadically as a function, and return the right argument. Let me know your thoughts: how should squad indexing behave? Should there be a way of achieving this in APL without axis specification (identity, zilde, etc), or do you have a different opinion entirely?
Why am I against axis specification with squad indexing?
I have an answer to my original question so I’ve quenched my thirst for knowledge and I have a workaround. The issue lies in performance. If we consider the same cube which was defined earlier (cube←?3 4 5⍴7
) there are several ways of getting at all of the rows, some more efficient than others:
]runtime 'cube[1;;2]' '1 2⌷[1 3]cube' '1(1 2 3 4)2⌷cube' '1(⍳4)2⌷cube' -compare
cube[1;;2] → 6.1E¯7 | 0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
1 2⌷[1 3]cube → 8.7E¯7 | +43% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
1(1 2 3 4)2⌷cube → 9.5E¯7 | +55% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
1(⍳4)2⌷cube → 1.1E¯6 | +84% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
Using axis-specification I am immediately hit by a 43% speed penalty and this is worsened further if I actually specify all rows by hand! Naturally, using ⍳4
in place of (1 2 3 4) yields a slower result still as a function is taking place to generate the indices.
Something about the omission of the indices with square-bracket indexing allows for a fast execution time, and this is something I’d like to see in squad indexing if it’s not already a feature.
APL Team Leader
James is an APL Programmer with a keen interest in mathematics. His love for computing was almost an accident. From a young age he always enjoyed using them- playing video games and such- but it was never considered that anything more would come from it. James originally had plans to pursue a career in finance. More about James.
Ask James about APL / APL Consultancy / APL Legacy System Support