The thing to note is that an operator is different from a function, since it might take functions as its operands (or, in this example, its single operand ⍺⍺), as well as arguments (in this example, ⍵).
Rather than read what's below (TLDR), you might want to look at the Legrand book https://www.dyalog.com/mastering-dyalog-apl.htm. It's a bit dated, but explains things like functions and operators rather well.
For the case at hand...
What's happening here is that we have an
operator, Key (⌸), which takes a left
operand, (here) a function, and a right
argument, the item whose major elements (items) are being evaluated. (I simplify: Key can also take a left argument, but let's pretend otherwise for now).
In our case,
Key calls the operand
{⍺ ⍵} many times, once for each unique element in the right argument. On each call,
Key sets ⍺ to be each unique element in turn-- one at a time, mind you-- and ⍵ to be a list of indices showing where that item occurred in the ORIGINAL array (the right argument to Key itself).
Operators often call their operand(s) with arguments--
⍺ and
⍵-- which are related to, but precisely NOT the same as their own (operator) arguments.
A simple case would be
where
+ is an OPERAND of
reduce / an operator.
Reduce appears to apply operand
+ between
all the elements of its right argument. You can see what's really going on by concocting a verbose equivalent:
Code: Select all
{⎕←('⍺=',⍺)'+'('⍵=',⍵),'=> (⍺+⍵)='(⍺+⍵) ⋄ ⍺+⍵}/1 2 3 4
⍺= 3 + ⍵= 4 => (⍺+⍵)= 7
⍺= 2 + ⍵= 7 => (⍺+⍵)= 9
⍺= 1 + ⍵= 9 => (⍺+⍵)= 10
10
So you can see that the operand {⎕←... ⋄ ⍺+⍵} is called several (N-1) times "by"
Reduce / with arguments related to
1 2 3 4, but obviously doled out according to the semantics of
reduction.
Cheers!