Rank Polymorphism Skill
"Loops are for peasants. Rank is for kings."
Core Concept
In rank-polymorphic languages:
- Operations apply to arrays automatically
- Rank (number of dimensions) determines how operations distribute
- No explicit loops — shape determines iteration
- Composition replaces control flow
1 2 3 + 10 20 30 ⍝ Vectorized: 11 22 33
+/ 1 2 3 4 ⍝ Reduce: 10
1 2 ∘.× 3 4 5 ⍝ Outer product: 2×3 matrix
Why It's Strange
- No for-loops — operations "just work" on any shape
- Rank as type — scalar, vector, matrix, tensor treated uniformly
- Tacit programming — point-free, no variable names
- Right-to-left —
3×2+1=3×(2+1)= 9
APL Basics
⍝ Scalar extension
2 + 1 2 3 ⍝ → 3 4 5
⍝ Vector operations
1 2 3 + 4 5 6 ⍝ → 5 7 9
⍝ Reduction
+/ 1 2 3 4 ⍝ → 10 (sum)
×/ 1 2 3 4 ⍝ → 24 (product)
⍝ Scan (cumulative)
+\ 1 2 3 4 ⍝ → 1 3 6 10
⍝ Outer product
1 2 ∘.× 3 4 5 ⍝ → 2×3 matrix: 3 4 5 / 6 8 10
⍝ Inner product
1 2 3 +.× 4 5 6 ⍝ → 1×4 + 2×5 + 3×6 = 32
BQN (Modern APL)
# Cleaner syntax, same ideas
+´ 1‿2‿3‿4 # Sum: 10
×˝ 2‿3⥊⟨1,2,3,4,5,6⟩ # Product of rows
# Rank operator (⎉)
+⎉1 mat # Apply + to rank-1 cells (rows)
# Under (⌾) - apply, transform, unapply
10 ⌾(2⊸⊑) 1‿2‿3 # → 1‿10‿3 (modify at index 2)
Rank Operator
The rank operator ⍤ (APL) or ⎉ (BQN) controls how functions distribute:
f⍤0 ⍝ Apply to scalars (rank 0)
f⍤1 ⍝ Apply to vectors (rank 1)
f⍤2 ⍝ Apply to matrices (rank 2)
Example:
mat ← 3 4 ⍴ ⍳12 ⍝ 3×4 matrix
+/⍤1 mat ⍝ Sum each row: 10 26 42
+/⍤2 mat ⍝ Sum entire matrix: 78
Leading Axis Theory
Arrays are organized by leading axes:
Shape: 2 3 4 5
│ │ │ └─ Innermost (columns)
│ │ └─── Third axis
│ └───── Second axis (rows)
└─────── Leading axis (frames)
Rank-1 cells: 5-vectors
Rank-2 cells: 4×5 matrices
Rank-3 cells: 3×4×5 cubes
J Language
+/ 1 2 3 4 NB. 10
*/ 1 2 3 4 NB. 24
1 2 */ 3 4 5 NB. Outer product
NB. Tacit (point-free)
mean =: +/ % # NB. sum divided by count
mean 1 2 3 4 5 NB. 3
Implementation Strategy
import numpy as np
def rank_apply(f, k, arr):
"""Apply f to rank-k cells of arr."""
if arr.ndim <= k:
return f(arr)
# Split into cells, apply, recombine
result = np.array([rank_apply(f, k, cell) for cell in arr])
return result
# Example
mat = np.arange(12).reshape(3, 4)
row_sums = rank_apply(np.sum, 1, mat) # Sum each row
Key Combinators
| APL | BQN | J | Meaning |
|-----|-----|---|---------|
| / | ´ | / | Reduce (fold) |
| \ | ` | \ | Scan (cumulative) |
| ¨ | ¨ | "0 | Each (map) |
| ∘. | ⌜ | */ | Outer product |
| ⍤ | ⎉ | " | Rank |
| ⍥ | ○ | &.: | Under |
| ⍣ | ⍟ | ^: | Power (iterate) |
Example: Game of Life
⍝ APL Game of Life in one line
life ← {↑1 ⍵∨.∧3 4=+/,¯1 0 1∘.⊖¯1 0 1∘.⌽⊂⍵}
No loops! The neighbor sum and rule application happen via rank.
Why No Loops?
⍝ Instead of:
⍝ for i in range(n):
⍝ for j in range(m):
⍝ result[i,j] = f(a[i], b[j])
⍝ Just write:
a ∘.f b ⍝ Outer product
⍝ Instead of:
⍝ total = 0
⍝ for x in arr:
⍝ total += x
⍝ Just write:
+/ arr ⍝ Reduce
Literature
- Iverson (1962) - "A Programming Language" (APL)
- Slepak et al. (2014) - "An Array-Oriented Language with Static Rank Polymorphism"
- Hui & Iverson (2004) - "J Dictionary"
- Marshall (2022) - "BQN: An APL for the Present"
End-of-Skill Interface
GF(3) Integration
# Trit arrays with rank polymorphism
import numpy as np
def gf3_sum(arr, axis=None):
"""Sum in GF(3) = sum mod 3."""
return np.sum(arr, axis=axis) % 3
def gf3_reduce(f, arr, axis=None):
"""Reduce with GF(3) conservation check."""
result = f(arr, axis=axis)
# Verify conservation
if (np.sum(arr) % 3) != (np.sum(result) % 3):
raise ValueError("GF(3) not conserved!")
return result
# Example: trit matrix
trits = np.array([[1, -1, 0], [0, 1, -1], [-1, 0, 1]])
row_sums = gf3_sum(trits, axis=1) # [0, 0, 0] - each row balanced!
Related Skills
numpy-broadcasting- Python's limited versioneinsum- Einstein summation (tensor rank)tacit-programming- Point-free styleconcatenative- Also combinator-based
Autopoietic Marginalia
The interaction IS the skill improving itself.
Every use of this skill is an opportunity for worlding:
- MEMORY (-1): Record what was learned
- REMEMBERING (0): Connect patterns to other skills
- WORLDING (+1): Evolve the skill based on use
Add Interaction Exemplars here as the skill is used.