⌨️ 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.

πŸ“Œ Array-At-A-TimeπŸ“Œ Right-to-Left EvaluationπŸ“Œ Symbolic NotationπŸ“Œ Iverson Turing Award
⍝ 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).

πŸ”— Rank (β‰’)⚑ Shape (⍴)πŸ“Š Depth (≑)πŸ“ Ravel Order
⍝ 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.

πŸ“ Element-wise⚑ Scalar ExtensionπŸ” Automatic BroadcastingπŸ“Š Signum (Γ—) function
⍝ 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.

πŸ”½ Reduce (/)πŸ“ˆ Scan (\\)πŸ“Š Key (⌸)πŸ” N-Wise Reduction
⍝ 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 (∘.)πŸ“ˆ Inner Product (.)⚑ Rank (⍀)πŸ“Š Matrix Multiply (+.Γ—)
⍝ 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.

πŸ“ Multi-D IndexingπŸ”§ Selective AssignmentπŸ“Š Pick (βŠƒ)⚑ At (@)
⍝ 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.

πŸ”„ ⌽ RotateπŸ“ ⍉ TransposeπŸ“Š ⍳ Index GeneratorπŸ” ⍎ Execute
⍝ 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 (Β¨)πŸ” Commute (⍨)πŸ“ Compose (∘)⚑ Power (⍣)
⍝ 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.

πŸ“ Dfns { }πŸ”— Trains (Forks/Hooks)πŸ“Š Guards (:]⚑ Recursion (βˆ‡)
⍝ 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).

πŸ”€ :If :ElseIfπŸ“Š :Select CaseπŸ›‘οΈ :TrapπŸ”„ :While :Repeat
⍝ 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.

πŸ“¦ Enclose (βŠ‚)πŸ“ Disclose (βŠƒ)πŸ“Š Mix (↑)πŸ”€ Split (↓)
⍝ 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.

πŸ“Ÿ Quad Input (βŽ•)πŸ“€ Quad Output (βŽ•β†)πŸ“ βŽ•CSVπŸ“Š βŽ•JSON
⍝ 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.

βˆ‡ Trad-fn delimiterπŸ“‚ NamespacesπŸ”§ βŽ•FXπŸ“ βŽ•CR
⍝ 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.

🎯 Unique MaskπŸ“Š Grade Up/Down⚑ PartitionπŸ” Self-Replicate
⍝ 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∘.βŒ½βŠ‚β΅}