β¨οΈ APL Deep Foundations
π― APL Design Philosophy & Execution Model
APL (A Programming Language, Kenneth E. Iverson, 1960s) is the original array programming language. It uses a unique symbolic character set and operates on entire arrays without explicit loops. APL follows the "code as data" philosophy β everything is an array. Modern implementations include Dyalog APL, GNU APL, and NARS2000.
Deep Explanation
APL evaluates right-to-left with no operator precedence (strict right-to-left). Every function has a rank (scalar, vector, matrix, etc.). Arrays can have any dimension (scalar to hyper-dimensional). The evaluation order makes APL extremely concise β solutions are often 10x shorter than other languages.
Why it matters: APL is used in finance (quantitative analysis), bioinformatics, physics simulations, and anywhere matrix operations dominate. Iverson won the Turing Award (1979) for his contributions to programming language theory.
β APL Deep Foundations
β Comments start with β (Lamp symbol)
β Simple array creation (Rho β΄ shapes)
arr β 2 3 β΄ β³6
β arr = 1 2 3
β 4 5 6
β Array operations work on entire arrays
2 Γ arr
β 2 4 6
β 8 10 12
β Right-to-left evaluation
2 Γ 3 + 4
β (3+4)=7, 2Γ7=14
β Inspect array shape
β΄arr
β 2 3
β Create sequence (Iota β³)
β³10
β 1 2 3 4 5 6 7 8 9 10π Arrays & Array-First Programming
π― Everything is an Array
APL has no scalars β even a single number is a 0-dimensional array (scalar). Arrays have rank (dimensions), shape, and depth.
Array Model & Terminology
Rank = number of dimensions (0=scalar, 1=vector, 2=matrix, 3+ = higher-rank). Shape = vector of dimension sizes. Depth = nesting level (for nested arrays). ravel order = row-major (last axis fastest).
β Array properties
vec β 1 2 3 4 5
β’vec β Rank = 1
β΄vec β Shape = 5
β‘vec β Depth = 1 (simple)
β Matrix creation
mat β 3 4 β΄ β³12
β 1 2 3 4
β 5 6 7 8
β 9 10 11 12
β Higher-rank array (3D)
cube β 2 3 4 β΄ β³24
β΄cube β 2 3 4
β’cube β 3 (rank)
β Scalar (0-dimensional)
scalar β 42
β’scalar β 0
β΄scalar β empty vector (no dimensions)
β Empty array
empty β 0 β΄ 0
β΄empty β 0π’ Scalar & Vector Operations
π― Primitive Scalar Functions
Scalar functions (+, -, Γ, Γ·, |, β, β, =, β , <, β€, >, β₯, β§, β¨, β², β±) apply element-wise to arrays.
Broadcasting & Scalar Extension
Scalar functions automatically broadcast β if one argument is scalar and the other is array, the scalar applies to every element. This is APL's version of broadcasting (long before NumPy). Mixed operations between different-shaped arrays require scalar extension.
β Vector arithmetic (element-wise)
a β 1 2 3 4
b β 5 6 7 8
a + b β 6 8 10 12
a Γ b β 5 12 21 32
b Γ· a β 5 3 2.333 2
β Scalar extension (broadcasting)
a + 10 β 11 12 13 14
100 - a β 99 98 97 96
β Boolean comparison
a < 3 β 1 1 0 0 (1=yes, 0=no)
a = b β 0 0 0 0
β Maximum/Minimum
3 β a β 3 3 3 4 (element-wise max)
3 β a β 1 2 3 3
β Remainder (modulo)
7 | a β 1 2 3 0
β Signum
Γ a-2 β Β―1 Β―1 0 1 (Β―1 = negative)π Reduction & Folding (βΏ, /, βΈ)
π― Reduce (/) & Scan (\\)
Reduction applies a dyadic function between elements of an array, collapsing one dimension. Scan produces intermediate results.
Reduction Along Any Axis
f/array reduces along the last axis. fβΏarray reduces along the first axis. fβ€axis can specify any axis. Key reduction (βΈ) groups values by keys. N-wise reduction uses moving windows.
β Sum reduction
+/1 2 3 4 5 β 15
Γ/1 2 3 4 5 β 120 (product)
β Matrix column sum (reduce along last axis)
mat β 2 3 β΄ β³6
β 1 2 3
β 4 5 6
+/mat β 1+2+3=6, 4+5+6=15 β 6 15
β Matrix row sum (reduce along first axis)
+βΏmat β 1+4=5, 2+5=7, 3+6=9 β 5 7 9
β Scan (cumulative)
+\1 2 3 4 5 β 1 3 6 10 15
β Key reduction (group by)
keys β 1 1 2 2 3
values β 10 20 30 40 50
{βΊ,β΅}βΈkeys,values β Group values by key
β N-wise reduction (moving window)
2+/1 2 3 4 5 β 3 5 7 9 (sum of pairs)π Outer Product & Rank Operator
π― Outer Product (β.) & Rank (β€)
Outer product applies a dyadic function between all combinations of elements. Rank operator controls function application depth.
Cartesian Product & Matrix Multiplication
β.f creates the outer product β result shape is (β΄a),β΄b. +.Γ is inner product (matrix multiplication). β€ (rank) specifies which sub-arrays to apply a function to β critical for higher-rank array manipulation.
β Outer product (all combinations)
a β 1 2 3
b β 10 20 30
a β.Γ b β Multiplication table
β 10 20 30
β 20 40 60
β 30 60 90
β Boolean outer product (equality matrix)
a β.= a β Identity matrix
β Inner product (matrix multiplication)
A β 2 3 β΄ β³6 β 2Γ3 matrix
B β 3 4 β΄ β³12 β 3Γ4 matrix
C β A +.Γ B β 2Γ4 result
β Rank operator (apply to each vector)
mat β 3 4 β΄ β³12
β½β€1 mat β Reverse each row (rank 1)
β½β€2 mat β Reverse each column (rank 2)
β Generalized inner product
a β¨.β§ b β Boolean OR-AND (reachability)
1 0 1 β¨.β§ 0 1 0 β 0 1 0π― Selective Assignment & Indexing
π― Indexing with [] and @
APL supports multi-dimensional indexing, selective assignment, and axis specification for partial array modification.
Powerful Indexing Patterns
Indexing: arr[1;2] or arr[1 2;3] (multiple indices). Selective assignment modifies only selected positions. Pick (β) extracts from nested arrays. At (@) applies function at specific positions.
β Basic indexing
mat β 3 4 β΄ β³12
mat[2;3] β Row 2, Column 3 (value 7)
mat[1;] β Entire row 1
mat[;2] β Entire column 2
β Multiple indices
mat[2 3; 1 4] β Submatrix: rows 2,3 and cols 1,4
β Selective assignment
mat[1;] β 99 β Set entire row 1 to 99
mat[2;2 3] β 0 β Set specific positions
β Boolean indexing (mask)
mask β mat > 10
mat[mask] β 0 β Set all >10 to 0
β Pick from nested array
nested β (1 2) (3 4) (5 6)
2 β nested β 3 4 (second element)
β At operator (apply at position)
arr β 1 2 3 4 5
(100)@3 arr β Replace 3rd element with 100βοΈ Primitive Functions (β΄, β³, β½, β)
π― Essential APL Symbols
Monadic (one argument) and dyadic (two arguments) primitive functions form APL's vocabulary. Many symbols have multiple meanings based on context.
Common Primitives Reference
β΄ (Rho): shape/mold, β³ (Iota): index generator, β½ (Rotate): reverse/rotate, β (Transpose): transpose, β (Format): to string, β (Execute): execute expression, β (Log): logarithm, * (Star): exponential.
β Shape (β΄) and Reshape (dyadic β΄)
β΄ 1 2 3 β 3 (shape)
3 4 β΄ β³12 β Reshape to 3Γ4
β Index generator (β³)
β³5 β 1 2 3 4 5
β³0 β empty vector
β Rotate (β½) and Reverse (β½ monadic)
β½ 1 2 3 4 β 4 3 2 1
2 β½ 1 2 3 4 β 3 4 1 2 (rotate left by 2)
β Transpose (β)
mat β 2 3 β΄ β³6
β mat β 3Γ2 matrix (swap axes)
β Format (β) and Execute (β)
β 123 β "123"
β "1 + 2 * 3" β 7
β Mathematical functions
*1 β 2.71828 (e^1)
β10 β 2.30259 (ln 10)
2 * 3 β 8 (power)
2 β 8 β 3 (log base 2)π Operators (Β¨, β¨, &, β)
π― Higher-Order Operators
Operators modify functions to create new derived functions. They are APL's higher-order functions β like decorators but more powerful.
Each, Commute, Compose
Each (Β¨) applies function to each element. Commute (β¨) swaps arguments. Compose (β) composes functions. Under (β£) applies function after inverse. Power (β£) repeats function N times.
β Each operator (apply to each element)
a β 1 2 3
b β 4 5 6
a +Β¨ b β (1+4) (2+5) (3+6) β each sum
{βΊ,β΅}Β¨ a b β Pairs: (1 4) (2 5) (3 6)
β Commute (swap arguments)
3 - 2 β 1
3 -β¨ 2 β -1 (commuted: 2 - 3)
-β¨ 5 β 0 - 5 = -5
β Compose (β)
f β -β1 β subtract 1
f 5 β 4
g β β½ββ β transpose then reverse
β Power operator (repeat)
fβ£3 5 β f applied 3 times: f(f(f(5)))
β Under operator (apply inverse)
β½β£Β―1 1 2 3 β reverse (inverse of reverse)
{β΅+1}β£Β―1 10 β 9 (inverse of add 1 is subtract 1)π DFNS (Direct Functions) & Trains
π― Lambda-style Functions
Direct functions (dfns) use braces { } with βΊ (left arg) and β΅ (right arg). Trains are tacit (point-free) function composition.
Tacit vs Explicit Programming
Dfns are modern APL functions β more readable than traditional trad-fns. Trains are APL's version of function composition: (f g h) becomes f (g h) (hook) or f g h (fork). Guard syntax β΅>0: β΅Γββ΅-1 β 1.
β Direct function (dfn)
add β {βΊ + β΅}
3 add 5 β 8
β Recursive factorial
fact β {β΅=0:1 β β΅Γβ β΅-1}
fact 5 β 120
β Guard syntax (if-then-else)
classify β {β΅<0:"negative" β β΅=0:"zero" β "positive"}
β Function trains (tacit)
average β (+βΏΓ·β’) β Sum divided by count
average 1 2 3 4 5 β 3
β Fork: (f g h)β΅ = (f β΅) g (h β΅)
mean β +βΏ Γ· β’ β Sum divided by length
β Hook: (f g)β΅ = β΅ f (g β΅)
double β +β¨ β x + x = 2x
β Multiple statements (separator β)
multi β {aββ΅+1 β bβaΓ2 β a+b}π‘οΈ Guards & Control Structures
π― Conditional Execution
APL has guards (:If :ElseIf :Else :EndIf) and a powerful :Select construct (pattern matching).
Traditional vs Dfn Control
Dfns use guard syntax (:). Traditional functions use :If blocks in control structures. :Select enables multiple dispatch. :Trap handles errors (similar to try-catch).
β Dfn guard syntax
absolute β {β΅β₯0:β΅ β -β΅}
β Multi-clause dfn
sign β {β΅<0:Β―1 β β΅=0:0 β 1}
β Traditional function with :If
β r β classify x
:If x < 0
r β 'negative'
:ElseIf x = 0
r β 'zero'
:Else
r β 'positive'
:EndIf
β
β :Select (pattern matching)
β r β handle code
:Select code
:Case 0
r β 'OK'
:Case 1
r β 'Warning'
:Else
r β 'Error'
:EndSelect
β
β :While loop
i β 1
:While i β€ 10
i β i + 1
:EndWhile
β :Trap (error handling)
:Trap 0
result β 1 Γ· 0
:Case
result β 'Division by zero'
:EndTrapπ¦ Nested Arrays & Box Notation
π― Heterogeneous Arrays
APL arrays can contain other arrays as elements (nested arrays). Box notation (β) encloses data into a scalar container.
Enclose, Disclose, and Mix
Enclose (β) creates a nested scalar. Disclose (β) extracts from nested array. Mix (β) converts vectors to matrix. Split (β) converts matrix to vector of rows. Nested arrays enable trees, JSON-like structures, and ragged arrays.
β Enclosing (create nested element)
scalar β β 1 2 3
β΄scalar β (scalar, rank 0)
β Nested array
nested β (1 2 3) (4 5 6) (7 8 9)
nested[2] β 4 5 6
β Disclose (extract from nesting)
β nested β 1 2 3 (first element)
β Mix (vertical concatenation)
v1 β 1 2 3
v2 β 4 5 6
β v1 v2 β 2Γ3 matrix
β Split (matrix to vectors)
mat β 3 4 β΄ β³12
β mat β Vector of 3 vectors (rows)
β Depth (nesting level)
β‘ nested β 2 (nested once)
β‘ ββ1 2 3 β 3 (double nested)
β Nested array with different types
mixed β 42 (1 2 3) "hello" β4 5
β‘mixed β 2πΎ I/O & System Functions (β)
π― Quad (β) Functions
System functions start with β (quad) β they handle I/O, environment, and system operations.
Keyboard Input & Output
β (quad alone) reads input. ββ outputs. βCSV reads/writes CSV files. βJSON handles JSON. βFIO provides POSIX file I/O. βDL delays execution. βAI gets account information.
β Input from user
name β β β Character input
age β β β Numeric input
β Output
ββ "Hello world"
ββ "The answer is ",β42
β File operations (Dyalog specifics)
β βNTIE 'file.txt' (open file)
β βNREAD tie ... (read)
β βNAPPEND tie ... (append)
β βCSV (CSV handling)
data β 3 2 β΄ 'Alice' 25 'Bob' 30 'Charlie' 35
βCSV 'output.csv' data
β βJSON
json β '{"name": "APL", "year": 1966}'
parsed β βJSON json
β Delay (seconds)
βDL 2 β Wait 2 seconds
β System time
βTS β Year Month Day Hour Minute Second Millisecond
β Get environment variable
βGETENV 'PATH'π§ User-Defined Functions & Namespaces
π― Traditional Functions (β)
Trad-fns use β (del) delimiters. Namespaces (.β) organize code and variables.
Code Organization
Traditional functions have local variables (βΊ and β΅ are arguments). :Namespace blocks create separated scopes. βFX fixes function objects. βCR shows function code.
β Traditional function (trad-fn)
β r β fib n
β Recursive Fibonacci
:If n<2
r β n
:Else
r β (fib n-1) + (fib n-2)
:EndIf
β
β Function with local variable
β r β average vector
total β +/vector
count β β’vector
r β total Γ· count
β
β Namespace
:Namespace Math
pi β 3.14159
e β 2.71828
square β {β΅Γβ΅}
:EndNamespace
β Access namespace
Math.pi
Math.square 10
β βFX (function fix - create from string)
code β 'fib' 'fib 0:0' 'fib 1:1' 'fib n:n+fib n-2'
βFX code
β βCR (character representation)
βCR 'fib' β Show function definitionπ§ APL Idioms & Problem Solving
π― Classic One-Liners
APL is famous for extremely concise solutions. Learning common idioms dramatically improves APL fluency.
Where Code is Thinking
These idioms demonstrate APL's power: Luhn algorithm in one line, Game of Life in 2 lines, Matrix inverse in 3 characters. The skill is thinking in arrays, not loops.
β Find unique (nub)
unique β {β΅[ββ΅]} β£ βͺ β Sorted unique
βͺ 1 2 2 3 3 3 β 1 2 3
β Grade up (sort indices)
β 5 2 8 1 9 β 4 2 1 3 5 (indices)
β΅[ββ΅] β Sort ascending
β Where (boolean to indices)
βΈ 1 0 1 0 1 1 β 1 3 5 6
β Prime numbers (Sieve of Eratosthenes)
primes β {(2=+βΏ0=(β³β΅)β.|β³β΅)/β³β΅}
primes 30 β 2 3 5 7 11 13 17 19 23 29
β First non-zero
{1ββ΅/β¨β΅β 0} 0 0 3 0 5 β 3
β Rotate diagonals (magic square)
magic β {β΅ β΅ β΄ β΅β1 }
β Rolling window average
moving_avg β {+/β΅}βΊ3 β Stencil operation
β Partition (split on conditions)
partition β {ββ€/β¨β½Β¨(β’ββ€1β¨+\)β΅}
β Life (Conway's Game of Life)
life β {β1 β΅β¨.β§3 4=+/,Β―1 0 1β.βΒ―1 0 1β.β½ββ΅}