Operators and axis

Dyalog
APL
Glyphs
Author

Jeremy Howard

Published

July 5, 2022

This post will explore some introductory operators (aka “higher order functions”) in APL.

]box on -style=max -trains=tree -fns=on
┌→─────────────────────────────────────┐
│Was ON -style=max -trains=tree -fns=on│
└──────────────────────────────────────┘

Axis

3 2⍴⍳6
┌→──┐
↓1 2│
│3 4│
│5 6│
└~──┘

Axis changes how the equal operator consumes the right argument. We specify a dimesion and we broadcast the operator across that dimension. In this case we are comparing the columns of the array to the left argument.

1 4 5 =[1] 3 2⍴⍳6
┌→──┐
↓1 0│
│0 1│
│1 0│
└~──┘
⎕←mat ← 2 3 ⍴ 10 20 30 40 50 60
┌→───────┐
↓10 20 30│
│40 50 60│
└~───────┘

Similarly we can modify the plus operator to broadcast along the columns.

mat+[1]1 2    ⍝ add along first axis
┌→───────┐
↓11 21 31│
│42 52 62│
└~───────┘

Comma functions

, (Comma)

monadic , (Ravel)

⎕ ← cube ← 2 2 2 ⍴ ⍳8
┌┌→──┐
↓↓1 2│
││3 4│
││   │
││5 6│
││7 8│
└└~──┘

Returns the elemenst as a vector

, cube
┌→──────────────┐
│1 2 3 4 5 6 7 8│
└~──────────────┘
, (1 2)(1 2)
┌→────────────┐
│ ┌→──┐ ┌→──┐ │
│ │1 2│ │1 2│ │
│ └~──┘ └~──┘ │
└∊────────────┘

monadic , (Ravel) with axis

'ABC'
┌→──┐
│ABC│
└───┘

We can use the axis modify insert a new dimension with ravel. We started with a single dimension, and we inserted a new one after it

,[0.5]'ABC'
┌→──┐
↓ABC│
└───┘
⍴'ABC'
┌→┐
│3│
└~┘

The fraction indicates where the new dimension is inserted

⍴,[0.5]'ABC'
┌→──┐
│1 3│
└~──┘

If we specify a null dimension the dimension is added at the end

⍴,[⍬]'ABC'
┌→──┐
│3 1│
└~──┘
2 2 2⍴⍳8
┌┌→──┐
↓↓1 2│
││3 4│
││   │
││5 6│
││7 8│
└└~──┘
⎕←M ← 2 3 4 ⍴ ⍳24
┌┌→──────────┐
↓↓ 1  2  3  4│
││ 5  6  7  8│
││ 9 10 11 12│
││           │
││13 14 15 16│
││17 18 19 20│
││21 22 23 24│
└└~──────────┘

Specifying more than one dimension will merge the two given dimensions

,[1 2]M
┌→──────────┐
↓ 1  2  3  4│
│ 5  6  7  8│
│ 9 10 11 12│
│13 14 15 16│
│17 18 19 20│
│21 22 23 24│
└~──────────┘
⍴,[1 2]M
┌→──┐
│6 4│
└~──┘
,[2 3]M
┌→──────────────────────────────────┐
↓ 1  2  3  4  5  6  7  8  9 10 11 12│
│13 14 15 16 17 18 19 20 21 22 23 24│
└~──────────────────────────────────┘
⍴,[2 3]M
┌→───┐
│2 12│
└~───┘

dyadic , (Catenate/Laminate (Join))

Joins arrays together

1 2 3 , 4 5 6
┌→──────────┐
│1 2 3 4 5 6│
└~──────────┘

Will be broadcast along the first dimension.

cube ← 2 2 2 ⍴ ⍳8
cube , 99
┌┌→─────┐
↓↓1 2 99│
││3 4 99│
││      │
││5 6 99│
││7 8 99│
└└~─────┘

dyadic , (Ravel) with axis

rect←3 2⍴⍳6
rect
┌→──┐
↓1 2│
│3 4│
│5 6│
└~──┘
⍴rect
┌→──┐
│3 2│
└~──┘

Add the element 10 to the end of each row

rect,10
┌→─────┐
↓1 2 10│
│3 4 10│
│5 6 10│
└~─────┘

We can modify laminate to add the given element to the columns (axis 1) instead of the rows (axis 2)

rect,[1]10
┌→────┐
↓ 1  2│
│ 3  4│
│ 5  6│
│10 10│
└~────┘

A fractional axis creates a new axis and laminates that onto the existing rect

rect,[0.5]10
┌┌→────┐
↓↓ 1  2│
││ 3  4│
││ 5  6│
││     │
││10 10│
││10 10│
││10 10│
└└~────┘
'HEADING',[0.5]'-'
┌→──────┐
↓HEADING│
│-------│
└───────┘

(Comma bar)

monadic (Table / Ravel items)

Very similar to ravel. Operates on the first axis by default instead of the last axis.

⍪1
┌→┐
↓1│
└~┘

This can be used to create columns instead of rows

⎕←,5⍴⎕A
⎕←⍪5⍴⎕A
┌→────┐
│ABCDE│
└─────┘
┌→┐
↓A│
│B│
│C│
│D│
│E│
└─┘
2 3 4⍴⎕A
┌┌→───┐
↓↓ABCD│
││EFGH│
││IJKL│
││    │
││MNOP│
││QRST│
││UVWX│
└└────┘

Ravels the dimensions down to 2 leaving the size of the first dimension unchanged and merging the others.

⍴⍪2 3 4⍴⎕A
┌→───┐
│2 12│
└~───┘
⍪2 3 4⍴⎕A
┌→───────────┐
↓ABCDEFGHIJKL│
│MNOPQRSTUVWX│
└────────────┘

dyadic (Catenate first)

Operates by catenating the first dimensions

1 2 3 ⍪ 4 5 6
┌→──────────┐
│1 2 3 4 5 6│
└~──────────┘
cube ← 2 2 2 ⍴ ⍳8
cube ⍪ 99
┌┌→────┐
↓↓ 1  2│
││ 3  4│
││     │
││ 5  6│
││ 7  8│
││     │
││99 99│
││99 99│
└└~────┘

Operator glyphs

/ (Slash)

monadic / (Reduce / N-wise Reduce)

monadic function (Reduce)

inserts the function on the right between the elements of the given array

1 2 3 4 5 —> 1+2+3+4+5

⎕ ← a ← ⍳5
+/a
┌→────────┐
│1 2 3 4 5│
└~────────┘
  
15
  

Can be used to multiply all elements together

a ← ⍳5
×/a
   
120
   
a ← ⍳3
÷/a
   
1.5
   

Find the maximum element in an array

a ← 4 6 2
⌈/ a
 
6
 

Find the minimum element in the array

a ← 4 6 2
⌊/ a
 
2
 
×/⍳5
   
120
   
!5
   
120
   
dyadic function (N-wise Reduce)

Windowed sum with window of 3:

3+/⍳4  ⍝ (1+2+3) (2+3+4)
┌→──┐
│6 9│
└~──┘

Windowed sum with window of 2:

2+/⍳4  ⍝ (1+2) (2+3) (3+4)
┌→────┐
│3 5 7│
└~────┘

Moving average

3÷⍨3+/⍳4
┌→──┐
│2 3│
└~──┘
0+/⍳4  ⍝ Identity element for +
┌→────────┐
│0 0 0 0 0│
└~────────┘
0×/⍳4  ⍝ Identity element for ×
┌→────────┐
│1 1 1 1 1│
└~────────┘
¯2,/⍳4⍝ (2,1) (3,2) (4,3)
┌→──────────────────┐
│ ┌→──┐ ┌→──┐ ┌→──┐ │
│ │2 1│ │3 2│ │4 3│ │
│ └~──┘ └~──┘ └~──┘ │
└∊──────────────────┘

Axis (with Monadic Operand)

Combining reduce with axis allows us to specify the dimension to reduce.

Sum the columns

mat←2 3⍴⍳6
+/[1]mat
┌→────┐
│5 7 9│
└~────┘

Sum the rows

mat←2 3⍴⍳6
+/[2]mat
┌→───┐
│6 15│
└~───┘
mat←2 3⍴⍳6
+/mat
┌→───┐
│6 15│
└~───┘

\ (Slope)

monadic \ (Scan)

Show all the intermediate steps of reduce

1 (1+2) (1+2+3) (1+2+3+4) (1+2+3+4+5)

a ← ⍳5
+\a
┌→──────────┐
│1 3 6 10 15│
└~──────────┘
a ← ⍳5
×\a
┌→───────────┐
│1 2 6 24 120│
└~───────────┘
⎕ ← a ← ⍳3
÷\a
┌→────┐
│1 2 3│
└~────┘
┌→────────┐
│1 0.5 1.5│
└~────────┘

(Slash Bar)

monadic (Reduce First)

Works similar to reduce. Operates on the first dimension rather than the last.

⎕←mat ← 2 3 ⍴ ⍳6
+/mat
┌→────┐
↓1 2 3│
│4 5 6│
└~────┘
┌→───┐
│6 15│
└~───┘
⎕←mat ← 2 3 ⍴ ⍳6
+/[1]mat
┌→────┐
↓1 2 3│
│4 5 6│
└~────┘
┌→────┐
│5 7 9│
└~────┘
+⌿mat
┌→────┐
│5 7 9│
└~────┘

(Slope Bar)

monadic (Scan first)

Similar to scan but operates on the first dimension rather than the last

⎕ ← mat ← 2 3 ⍴ ⍳6
+⍀mat
┌→────┐
↓1 2 3│
│4 5 6│
└~────┘
┌→────┐
↓1 2 3│
│5 7 9│
└~────┘

(Jot Diaresis)

dyadic (Rank)

trace←{⍺←⊢⋄⎕←'⍺: '⍺ '⍵: '⍵⋄ ⍺ ⍺⍺ ⍵} ⍝ explainer function

⍤ lets you specify the dimensions of the matrix to pass into the next function. In this case we only want plus reduce first to operate across rows.

⎕←cube ← 2 3 4 ⍴ ⍳24
(+⌿⍤1)cube
┌┌→──────────┐
↓↓ 1  2  3  4│
││ 5  6  7  8│
││ 9 10 11 12│
││           │
││13 14 15 16│
││17 18 19 20│
││21 22 23 24│
└└~──────────┘
┌→───────┐
↓10 26 42│
│58 74 90│
└~───────┘
(+⌿trace⍤1)cube ⍝ show the input to pluse reduce first
┌→────────────────┐
│ ┌→──┐ ┌→──────┐ │
│ │⍵: │ │1 2 3 4│ │
│ └───┘ └~──────┘ │
└∊────────────────┘
┌→────────────────┐
│ ┌→──┐ ┌→──────┐ │
│ │⍵: │ │5 6 7 8│ │
│ └───┘ └~──────┘ │
└∊────────────────┘
┌→───────────────────┐
│ ┌→──┐ ┌→─────────┐ │
│ │⍵: │ │9 10 11 12│ │
│ └───┘ └~─────────┘ │
└∊───────────────────┘
┌→────────────────────┐
│ ┌→──┐ ┌→──────────┐ │
│ │⍵: │ │13 14 15 16│ │
│ └───┘ └~──────────┘ │
└∊────────────────────┘
┌→────────────────────┐
│ ┌→──┐ ┌→──────────┐ │
│ │⍵: │ │17 18 19 20│ │
│ └───┘ └~──────────┘ │
└∊────────────────────┘
┌→────────────────────┐
│ ┌→──┐ ┌→──────────┐ │
│ │⍵: │ │21 22 23 24│ │
│ └───┘ └~──────────┘ │
└∊────────────────────┘
┌→───────┐
↓10 26 42│
│58 74 90│
└~───────┘

Sum the columns

⎕←mat ← 3 4 ⍴ ⍳12
+⌿mat
┌→─────────┐
↓1  2  3  4│
│5  6  7  8│
│9 10 11 12│
└~─────────┘
┌→──────────┐
│15 18 21 24│
└~──────────┘

For each of the 3 4 (the first 2 dimensions) matrices in the larger cube apply plus reduce first

⎕←cube
(+⌿⍤2)cube
┌┌→──────────┐
↓↓ 1  2  3  4│
││ 5  6  7  8│
││ 9 10 11 12│
││           │
││13 14 15 16│
││17 18 19 20│
││21 22 23 24│
└└~──────────┘
┌→──────────┐
↓15 18 21 24│
│51 54 57 60│
└~──────────┘

Given ⍺ and ⍵ arguments we can specify dimensions for each. In the following we take the ⍺ argument by element and the ⍵ argument by row

⎕←mat
1 2 3 (+trace⍤0 1) mat
┌→─────────┐
↓1  2  3  4│
│5  6  7  8│
│9 10 11 12│
└~─────────┘
┌→────────────────────────┐
│ ┌→──┐   ┌→──┐ ┌→──────┐ │
│ │⍺: │ 1 │⍵: │ │1 2 3 4│ │
│ └───┘   └───┘ └~──────┘ │
└∊────────────────────────┘
┌→────────────────────────┐
│ ┌→──┐   ┌→──┐ ┌→──────┐ │
│ │⍺: │ 2 │⍵: │ │5 6 7 8│ │
│ └───┘   └───┘ └~──────┘ │
└∊────────────────────────┘
┌→───────────────────────────┐
│ ┌→──┐   ┌→──┐ ┌→─────────┐ │
│ │⍺: │ 3 │⍵: │ │9 10 11 12│ │
│ └───┘   └───┘ └~─────────┘ │
└∊───────────────────────────┘
┌→──────────┐
↓ 2  3  4  5│
│ 7  8  9 10│
│12 13 14 15│
└~──────────┘

dyadic (Atop)

⍤ used dyadically is a function application rule

f⍤g X → f(gX) → fgX X f⍤g Y → f X g Y

f ← *⍤÷
⎕←*(÷3)
⎕←f 3
           
1.395612425
           
           
1.395612425
           
⎕←*2÷3
⎕←2 f 3
           
1.947734041
           
           
1.947734041
           

(Jot)

dyadic (Bind)

Can be used for partial function application. Binds the right argument 2 to the power function returning a new function that takes only a single argument

sqr ← *∘2
sqr 3
 
9
 

Can bind the left argument as well

pow2 ← 2∘*
pow2 3
 
8
 

dyadic (Beside)

Another function composition rule

f∘g X → f(gX) → fgX X f∘g Y → X f g Y

f ← *∘÷
*(÷3)
           
1.395612425
           
f 3
           
1.395612425
           
2 f 3
          
1.25992105
          
2 * (÷3)
          
1.25992105
          
2*÷3
          
1.25992105
          

(Circle diaresis)

dyadic (Over)

Another function composition rule.

f⍥g Y → f(gX) → fgX X f⍥g Y → (g X)f(g Y)

f ← *⍥÷
*(÷3)
           
1.395612425
           
f 3
           
1.395612425
           
2 f 3
           
0.793700526
           
(÷2)*÷3
           
0.793700526
           
10 (÷⍥!) 6   ⍝ P(10,4)
    
5040
    
(!10)÷!(10-4)  ⍝ P(10,4)
    
5040
    

(Star Diaeresis)

dyadic (Power operator)

S ← +∘1
S 0
 
1
 

⍣ Calls a function the given number of times.

S(S(S 0))

(S⍣3) 0
 
3
 
add ← {(S⍣⍺) ⍵}
2 add 3
 
5
 
mult ← {⍺ (add⍣⍵) 0}
3 mult 4
  
12
  
P ← S⍣¯1
P 3
 
2
 
(S⍣¯3) 5
 
2
 
sqr ← *∘2
(sqr⍣¯1)9
 
3
 
pow ← {⍺ (mult⍣⍵) 1}
2 pow 3
 
8
 
1 +∘÷⍣= 1
           
1.618033989
           
f ← +∘÷
1 f 1
 
2
 
1 f 2
   
1.5
   
1 f 1.5
           
1.666666667
           
1 (f⍣15) 1
           
1.618034448
           
1 (f⍣=) 1
           
1.618033989
           

Linear Algebra

. (Dot)

Dyadic . (Inner Product)

The ⍵⍵ operator specifies how elements are combined. The ⍺⍺ argument specifies how the results of the ⍵⍵ operation are combined.

(1×4) + (2×5) + (3×6)

1 2 3 +.× 4 5 6  ⍝ Dot product
  
32
  

(3=3)∧(3=3)∧(3=3)∧(3=3)

3 ∧.= 3 3 3 3  ⍝ All-equal
 
1
 

(1×1)+(2×3)    (1×2)+(2×4)

(3×1)+(4×3)    (3×2)+(4×4)

⎕←mat←2 2⍴⍳4
mat +.× mat   ⍝ matrix product
┌→──┐
↓1 2│
│3 4│
└~──┘
┌→────┐
↓ 7 10│
│15 22│
└~────┘

In this case we are going to duplicate the ⍵ argument. Once for each element of the ⍺ argument. The first one is multiplied by the first element of the ⍺ argument. The second by the second element, etc.

1× 4 5 6 7

2× 4 5 6 7

3× 4 5 6 7

1 2 3 ∘.× 4 5 6 7  ⍝ Special case: outer prodct
┌→──────────┐
↓ 4  5  6  7│
│ 8 10 12 14│
│12 15 18 21│
└~──────────┘

(Domino;Quad Divide)

Monadic (Matrix Inverse Of)

mat←2 2⍴⍳4
⎕←inv←⌹ mat
┌→────────┐
↓¯2    1  │
│ 1.5 ¯0.5│
└~────────┘
inv +.× mat  ⍝ Identity
┌→──┐
↓1 0│
│0 1│
└~──┘

Dyadic (Matrix Division By)

⎕←div←5 6 ⌹ mat
┌→─────┐
│¯4 4.5│
└~─────┘
mat +.× div
┌→──┐
│5 6│
└~──┘

Custom operators

f ← *∘2
d ← 0.01
x ← 3
((f (x+d)) - f x) ÷ d
    
6.01
    
d ← 0.0001
((f (x+d)) - f x) ÷ d
      
6.0001
      
grad ← {((⍺⍺ ⍺+⍵) - ⍺⍺ ⍺) ÷ ⍵}
3 f grad 0.01
    
6.01
    

Diaeresis and Tilde Diaeresis

(Tilde Diaeresis)

dyadic (Commute)

Modifies the given function so its arguments are swapped.

3-2
 
1
 
2-3
  
¯1
  
3-⍨2
  
¯1
  

Normally to use a mask to select elements the mask is the ⍺ argument to /. If we wanted to right this out we would need to calculate the mask first.

(≠v)/v

v←22 10 22 22 21 10 5 10
v/⍨≠v
┌→─────────┐
│22 10 21 5│
└~─────────┘
grad ← {⍵ ÷⍨ (⍺⍺ ⍺+⍵) - ⍺⍺ ⍺}
3 f grad 0.01
    
6.01
    

Can also be used to reflect the ⍵ argument to become the ⍺ argument as well.

3 × 3

pow ← ×⍨
pow 3
 
9
 

dyadic (Constant)

zero ← 0⍨
2 zero 5
 
0
 

¨ (Diaresis)

monadic ¨ (Each)

⎕ ← a ← (1 2 3 4)(5 6 7)
┌→──────────────────┐
│ ┌→──────┐ ┌→────┐ │
│ │1 2 3 4│ │5 6 7│ │
│ └~──────┘ └~────┘ │
└∊──────────────────┘

Apply +/ to each of the elements of a. Each element is itself an array. So we sum those up.

+/¨a
┌→────┐
│10 18│
└~────┘
⎕ ← b ← (1 2 3)(4 5 6)
┌→────────────────┐
│ ┌→────┐ ┌→────┐ │
│ │1 2 3│ │4 5 6│ │
│ └~────┘ └~────┘ │
└∊────────────────┘

Distribute the plus and an element to each of the elements of b.

2 + 1 2 3

3 + 4 5 6

2 3 +¨ b
┌→────────────────┐
│ ┌→────┐ ┌→────┐ │
│ │3 4 5│ │7 8 9│ │
│ └~────┘ └~────┘ │
└∊────────────────┘