μ Array Language · Reference Documentation May 2026

μ

grammar reference

Grammar

μ is parsed right-to-left. A program is a sequence of expressions separated by newlines or semicolons. The last expression in a sequence is the result.

program    ::= sequence EOF
sequence   ::= expr (';' expr)*
expr       ::= name ':' expr          -- assignment
             | verb_expr
verb_expr  ::= composition verb adverb? verb_expr   -- dyadic
             | verb adverb? verb_expr              -- monadic / adverb
             | composition
composition ::= strand ('.' strand)*               -- function composition
strand     ::= atom+                               -- juxtaposition / apply
atom       ::= '(' sequence ')'
             | '[' sequence (';' sequence)* ']'    -- vector literal
             | '{' arg_list? sequence '}'  adverb?   -- lambda
             | name
             | integer
             | float
             | char_literal
             | string_literal
             | symbol
arg_list   ::= '[' name (';' name)* ']'
vector     ::= '[' sequence (';' sequence)* ']'   -- bracket vector (expr1;expr2;...)
adverb     ::= '/' | '\'              -- fold / scan (after a verb)
             | '/:'                   -- each-right (after a verb or function)
             | '\:'                   -- each-left  (after a verb or function)
             | "'"                    -- each       (postfix on a name or lambda)

Verbs

Verbs are single characters. Their meaning depends on arity (monadic = one argument, dyadic = two).

verbmonadicdyadic
+transpose (flip) add
-negate subtract
*first element multiply
*.— matrix multiply
%reciprocal divide
%.— matrix solve (Ax=b)
!iota (0..n-1) modulo
#count take
@type tag index
=— equal (element-wise)
<sort ascending min (returns lesser value); </ list = min of list
>sort descending max (returns greater value); >/ list = max of list
,— join / concatenate lists or atoms; ,/ = raze (flatten list-of-lists)
|list comprehension separator — see List Comprehensions
?generate n uniform random floats in [0,1)—
_floor drop

Adverbs

Adverbs modify a verb or function to produce a new function. The left operand determines the mode at evaluation time.

syntaxnamemeaningexample
v/ listfold reduce list with verb v, right-to-left; ,/ = raze (flatten list-of-lists)+/ 1 2 3 → 6; ,/((1 2);(3 4)) → 1 2 3 4
v\ listscan running reduction, returns list; ,\ = cumulative join+\ 1 2 3 → 1 3 6
f' listeach map single-arg function f over every element{x*x}' 1 2 3 → 1 4 9
n f/ xiterate-foldapply f to x exactly n times, return final value3 {x+1}/ 0 → 3
n f\ xiterate-scanapply f to x exactly n times, return all n+1 states3 {x+1}\ 0 → 0 1 2 3
f/ xconvergeapply f repeatedly until result stabilises{(x+2.0%x)*0.5}/ 1.0 → 1.4142…
f/: [x; list]each-rightapply two-arg f[x; yi] for each element yi of list{[a;b] a+b}/: [10; 1 2 3] → 11 12 13
f\: (list) xeach-leftapply two-arg f[xi; x] for each element xi of list{[a;b] a*b}\: (1 2 3) 10 → 10 20 30
{[a;x;i]…}/[(seed); list]ternary foldreduce list with a 3-arg step function receiving accumulator, element, and 0-based index; returns final accumulator{[a;x;i] a+x}/[(0); (1 2 3)] → 6
{[a;x;i]…}\[(seed); list]ternary scansame as ternary fold but returns all n+1 states (seed + one result per element){[a;x;i] a+x}\[(0); (1 2 3)] → 0 1 3 6

Disambiguation of f/ left operand at evaluation time (mirrors K):


Function Composition

The . operator composes two functions: f . g creates a new function that applies g first, then f to the result: (f . g)(x) = f(g(x)).

syntaxmeaningexample
f . gcompose: apply g, then finc: {x+1}; dbl: {x*2}; h: inc . dbl; h 5 → 11
f . g . hchained compositionsqrt . sum . {x*x} → Euclidean norm
(f . g)' listcomposed function with each(sqrt . {x*x})' 1 2 3 → identity map
math . fmath keywords are first-class functionssqrt . exp' 0 1 2 → √e⁰ √e¹ √e²

Composition has higher precedence than verbs but lower than strands: sqrt . sq 9 parses as sqrt . (sq 9), not (sqrt . sq) 9. To apply the composition: (sqrt . sq) 9 or f: sqrt . sq; f 9. Math keywords bind to one atom: sqrt sq 9 is sqrt(sq 9) = sqrt 81 = 9.

I/O keywords

File and data keywords for reading, writing, and parsing structured data. In the CLI, read and write operate on local file paths. In the WASM playground, csv works via the JavaScript fetch bridge (MuWASM.loadCSV).

keyworddescriptionexample
read "path" Read a text file into a list of char-list lines read "data.csv" → ("a,b";"1,2";"3,4")
csv "path" Read & parse CSV file → column-oriented table (headers; columns). Headers become symbols; values auto-detect as integer, float, or string. csv "data.csv" → (`a `b;(1 2;3 4))
csv lines Parse an in-memory list of char-list lines as CSV (same output format) csv (read "f.csv")
write["path"; data] Write a table or list of lines to a file (CLI only). Tables are written as CSV with headers. write["out.csv"; t]

The table format (headers; columns) is a 2-element list: element 0 is a list of symbols (column names), element 1 is a list of column vectors. Index with t@0 for headers and (t@1)@i for column i.


Conditional semantics (cond)

Inside a lambda body, a semicolon-separated sequence acts as a K-style conditional chain, not a plain sequence:

{e0; e1; e2; e3}   -- if e0 truthy → return e1; else if e2 truthy → return e3; ...

Each even-indexed expression is a condition; if truthy its successor is evaluated and returned, stopping evaluation. A tail with no matching condition returns nil. A single expression {e0} is returned directly (no cond logic).

cfib:{x=0; 1; x=1; 1; (cfib x-1)+(cfib x-2)}
cfib 10   -- → 89

-- Truthiness: non-zero values are truthy.
-- Dyadic < and > return the min/max value, not a boolean:
--   0>x  is truthy when x>0 (returns x), falsy when x=0 (returns 0)
-- Boolean greater-than idiom: 0>a-b  (truthy when a>b, falsy otherwise)

Lambda forms

formargsexample
{expr} implicit x (single arg); x y if body uses y {x+1} 5 → 6
{[x;y] expr} explicit named args {[a;b] a*b} 3 4 → 12
{expr}/ map body over list, then fold result with + {x*x}/ 1 2 3 → 14
{expr}\ map body over list, then scan result with + {x*x}\ 1 2 3 → 1 5 14

List Comprehensions

List comprehensions provide a concise way to create lists from existing lists, with optional filtering. They desugar to nested each' expressions.

[expr | var <- list; guard]

| introduces the generator. Multiple generators nest left-to-right. An optional guard (after ;) filters elements — only elements for which the guard is truthy are included in the result.

patternmeaningexample
[x*x | x <- 1 2 3] map: square each element → 1 4 9
[x | x <- !10; (2!x)=0] filter: even numbers 0–9 (2!x = x mod 2) → 0 2 4 6 8
[[i;j] | i <- !3; j <- !3] multiple generators: cartesian product → [0;0] [0;1] ... [2;2]
[matget[cm;i;j] | i <- !10; j <- ((i+1)+!((10-i)-1))] practical: upper triangle of correlation matrix extract off-diagonal elements

Desugaring: [x*x | x <- 1 2 3] compiles to {[x] x*x}' 1 2 3. Guards compile to filter-each expressions. This ensures efficient execution via μ's bump allocator with automatic scratch-reset for memory efficiency.


Plot & visualisation keywords

In the CLI, plot verbs save SVG files to the current directory (filename derived from the chart title, or a timestamp if untitled) and print the saved path. In the WASM playground, they render to an inline canvas.

keyworddescriptionexample
plot y Line plot of y values; x = 0, 1, 2, … plot 1 4 9 16
plot[x; y] Line plot of y vs explicit x plot[1 2 3; 2 4 6]
plot[x; y; `Title] As above with a symbol title plot[xs; ys; `Returns]
plotpng y Same as plot but outputs PNG (requires rsvg-convert or ImageMagick) plotpng 1 4 9 16
plothist counts Bar chart of a counts list; x = 0, 1, 2, … plothist 3 7 4 2
plothist[bins; counts] Bar chart with explicit bin centres plothist[0.0 0.5 1.0; 3 7 4]
plothist[counts; `Title] or plothist[bins; counts; `Title] As above with a symbol title plothist[h; `Dist]
plothist[bins; series_list] Multi-series grouped bar chart; series_list is a list of equal-length count vectors plothist[xs; (s1; s2; s3)]
plothline val Overlay a dashed horizontal reference line at val on the most recent plot plot 1 4 9; plothline 5
heatmap[matrix] Render a matrix (list-of-lists) as a colour grid heatmap[cut 3 !9]
heatmap[matrix; `Title] Heatmap with a symbol title heatmap[c; `Corr]
plot3d[zs] 3-D surface of a matrix of z values; x and y = 0, 1, 2, … plot3d[m]
plot3d[xs; ys; zs] or plot3d[xs; ys; zs; `Title] Full 3-D surface with explicit grid coordinates plot3d[xs; ys; zs; `Surface]

The hist keyword computes bin counts without plotting:

hist[n; vals]       -- divide vals into n equal-width buckets; returns count list
hist[4; 0.0 0.5 1.0 1.5]  -- → 1 1 1 1

Layered chart composition

The chart verb composes multiple layer descriptors into a single chart with shared axes, auto-ranging, and palette colors. Layer constructors return tagged lists that chart interprets at render time.

keyworddescriptionexample
chart[layers...; `Title] Compose layers into a single chart (up to 16) chart[line[x;y]; hline 5; `MyChart]
line[x; y] Layer: polyline with dots line[0 1 2; 1 4 9]
scatter[x; y] Layer: scatter plot (circles) scatter[xs; ys]
band[x; ylo; yhi] Layer: filled region between ylo and yhi band[x; lo; hi]
bar[bins; counts] Layer: histogram bars bar[xs; cs]
hline val Layer: horizontal dashed reference line hline 2.5
vline val Layer: vertical dashed reference line vline 100
diag[] Layer: y = x diagonal reference diag[]
step[x; y] Layer: step function (staircase) step[xs; cdf]
qqplot data or qqplot[data; `Title] QQ normal probability plot (scatter + diagonal) qqplot[samples; `QQ]

Named math keywords

Math keywords are first-class functions — they live in the environment like any other name. They work element-wise over lists and can be used with adverbs, assigned to variables, or passed as arguments.

keywordoperationexample
sqrtsquare root sqrt 4.0 → 2.0
abs absolute value abs (-3) → 3.0
exp ex exp 0 → 1.0
log natural logarithm log 1.0 → 0.0
cos cosine (radians) cos 0 → 1.0
sin sine (radians) sin 0 → 0.0
tan tangent (radians) tan 0 → 0.0
acosarc cosine — acos(-1) gives πacos(-1) → 3.14159…
asinarc sine (radians) asin 0 → 0.0
atanarc tangent (radians) atan 1 → 0.7854…

Math keywords bind to a single adjacent atom — the same as a monadic verb. sqrt x * y evaluates as (sqrt x) * y. When the argument is a compound expression, use parentheses: sqrt(a*a + b*b). neg is a verb alias for monadic - with identical atom-binding: neg x * y = (-x) * y.

Because math keywords are first-class, they work directly with adverbs and assignment:

sin' 1 2 3            -- → 0.8414… 0.9092… 0.1411…  (each)
f:sin; f' 1 2 3       -- assign and use via each
sin(1 2 3)            -- parenthesised list: same result

Reference cells

Reference cells provide mutable state — a container that holds a value which can be read and updated. They enable imperative patterns like counters, accumulators, and shared mutable state.

keyworddescriptionexample
ref x Create a reference cell containing x r:(ref 42) → ref[42]
get r Read the current value from reference r get r → 42
set[r; y] Update reference r to contain y; returns y set[r; 100] → 100
mutate[r; f] Apply function f to current value, update r, return new value mutate[r; {x+1}] → 43

References print as ref[value] showing their current contents. They are first-class values and can be stored in lists, passed to functions, etc.

counter:{[n]
  r:(ref 0);
  {mutate[r; {x+1}]}' !n;   -- increment n times
  get r                     -- return final count
}
counter 5  -- → 5

Control flow

while is the only looping construct. It evaluates a condition expression repeatedly, running the body statements as long as the condition is truthy. It returns the value of the last body statement evaluated, or nothing if the body never executes.

while[condition; stmt1; stmt2; ...]
exampleresultnotes
cnt:0; while[cnt<3; cnt:cnt+1] 3 Simple counter — single body statement
i:0; s:0; while[i<3; i:i+1; s:s+i; s] 6 Multiple statements; last value (s) returned
x:1; while[x<=100; x:x*2; x] 128 First power of 2 greater than 100
eps:1.0; while[eps>0.001; eps:eps*0.5; eps] 0.000976… Converge to small epsilon
x:5; while[x<0; x:x+1] (nothing) Body never runs — condition is false from the start

while modifies its local bindings in place. Variables updated in the body (e.g. cnt above) are visible to subsequent iterations and after the loop. For purely functional iteration prefer n f/ seed (iterate-fold).


Global variables

A dot-prefix on a name (.name) reads from or writes to a shared global namespace that persists across all closures and is never captured by a snapshot. This mirrors K-style globals and is useful for mutable shared state that must be visible inside deeply nested lambdas.

.x: 42             -- write global x
.x                 -- read global x → 42
.x: .x + 1        -- update global x → 43

The key distinction from local assignment is capture semantics:

.base:100
snap:{.base+x}     -- closes over nothing; reads .base live
.base:999
snap 1             -- → 1000  (sees updated .base)

Global assignment inside a lambda writes back to the global namespace, not a local copy:

inc_global:{.counter:.counter+1}
.counter:0
inc_global[]; inc_global[]; .counter   -- → 2

Literals

literalsyntaxexample
integer decimal digits, optional leading -42, -7
float digits with ., or integer with f suffix3.14, -1.0, 1f, 0f
char "c" (single-char string) or 'c' / 'c (apostrophe form) "a", 'a'
string "hello" — double-quoted; produces a list of char values; supports \n \t \" \\ escapes "hi"
symbol `name (backtick prefix) `hello
list strand space-separated atoms 1 2 3

Assignment & sequencing

  x: 42              -- assign 42 to x
  f: {x+1}           -- assign lambda to f
  sum:+/             -- verb alias: sum is +/ fold
  a:1; b:2; a+b      -- semicolon sequences expressions; result is last

REPL commands

commandaction
\l path load and execute a .mu source file
\S n seed the random number generator with integer n
\d toggle debug mode (prints AST + memory stats)
\t toggle type annotations on output (appends :type to each result)
\p name set plot colour palette (e.g. \p warm)
\\ quit
:q quit

Example: Black-Scholes Monte Carlo

Box-Muller transform and Monte Carlo pricing of a European call option. Demonstrates random number generation, antithetic variates, and vectorised arithmetic. Uses explicit named-arg lambdas to avoid the implicit-x/y/z wrapping rule; avoids naming intermediate variables x, y, or z (single-char implicit arg names) at the top level.

\S 7

// Box-Muller: produce n standard normal variates
bm:{[n] sqrt(-2*log(1.0-?n)) * cos(2*acos(-1)*?n)}

// European call: s0=spot, k=strike, r=rate, sig=vol, t=maturity, n=paths
mcCall:{[s0;k;r;sig;t;n] half:_(n%2);zz:bm half;zz:zz,-zz;drift:(r-0.5*sig*sig)*t;st:s0*(exp(drift))*(exp(sig*sqrt(t)*zz));exp(-r*t)*mean(0|st-k)}

mcCall 100 100 0.05 0.2 1.0 100000
// → ~10.45  (closed-form Black-Scholes: 10.4506)

Notes on μ syntax:


Example: Asian Option Monte Carlo

Arithmetic-average Asian call option priced by path simulation. Uses iter to accumulate payoffs one path at a time (avoids pool exhaustion for large n), and sums (cumulative-sum scan, from stdlib/stdlib.mu) to build the price path from log-returns.

\S 7

// Box-Muller: produce n standard normal variates
bm:{[n] sqrt(-2*log(1.0-?n)) * cos(2*acos(-1)*?n)}

// Asian call: s0=spot, k=strike, r=rate, sig=vol, t=maturity, m=steps, n=paths
// Arithmetic average of m in-period prices forms the payoff.
mcAsian:{[s0;k;r;sig;t;m;n] exp(-r*t)*((n {[acc] acc+(0|(mean(s0*exp(sums ((r-0.5*sig*sig)*(t%m))+(sig*sqrt(t%m))*bm m)))-k)}/ 0.0)%n)}

mcAsian 100 100 0.05 0.2 1.0 12 10000
// → ~6.13  (arithmetic-average Asian call; less than European ~10.45 because averaging dampens volatility)

Notes on mcAsian: