Demos

Small programs in X_eTaL, a typed array language, that make something worth watching. Each one shows its program beside the result, so you can see a whole loop nest happen as one array expression. The machine-learning demos (a 1.58-bit network, an MoE routing microscope, a tiny CNN, attention) are in X_eTaL-ML.

X_eTaL is an APL-family array language designed today: whole-array programming and terse composition, with inferred static types and typed functional composition from Haskell, explicit, checked interfaces in the spirit of Rust, and plain ASCII source drawn as readable typography.

Extensible three ways: libraries extend the vocabulary (ready), macros extend what the language can say (new), native extensions extend the machine (through a bridge today).

Life microscope Live

Life microscope

Conway's Life in one line of X_eTaL, with every array the line builds drawn: the nine shifted boards, their sum, the two masks, the next board. Click a cell to see its arithmetic.

Why arrays: Nine shifted copies of the board, summed: every cell's neighbors counted at once, with no loop over cells and none over neighbors.

ᵘl̲ife ← { ('+ r̲/₁₂ -1 0 1 o̲-₁₂ ⍵) { (⍺ = 3) + ⍵ × ⍺ = 4 } ⍵ }
rotate along axesreduce over axescomparison masksscalar extension
Mandelbrot Live

Mandelbrot

Every point of the picture iterated at once: z becomes z * z + c over the whole grid. Step k up and watch the set appear; click a point for its orbit, or zoom in.

Why arrays: z becomes z * z + c for every pixel at once: the whole grid is the argument, and a mask freezes the points that have escaped.

a ← (inside × cr + (zr × zr) − zi × zi) + (1 − inside) × zr
broadcasting with tablefunction powermasksrank-3 state
Julia sets Live

Julia sets

One X_eTaL function gives the Mandelbrot set (c the grid) and every Julia set (c one number, extended over the grid). Pick c on the Mandelbrot map, or play c around its edge and watch the Julia set morph.

Why arrays: The same step as Mandelbrot: c is one number here and a whole grid there, and the same code serves both (a single value extends over the grid).

inside ← f̲loat 4 ≥ (zr × zr) + zi × zi
scalar extensionbroadcasting with tablefunction powerdyadic functions
Reaction-diffusion Live

Reaction-diffusion

Gray-Scott chemistry on a grid: mazes, coral and spots grow by themselves. Each step is four shifts and a few products over the whole grid; click a cell to see its arithmetic, or drop more chemical.

Why arrays: Diffusion is four rotated copies of the grid minus four times the grid; the reaction is elementwise. Both apply to every cell at once.

ᵘl̲ap ← { x → ((1 o̲-₁ x) + (-1 o̲-₁ x) + (1 o̲-₂ x) + -1 o̲-₂ x) − 4.0 × x }
stencils by rotationelementwise arithmeticfunction powerrank-3 state
Wave tank Live

Wave tank

The wave equation on a grid: waves pass through a double slit and interfere, bend through a lens of slow water, and ripple where you click. Walls, sources and lenses are masks; each step is a stencil over the whole grid.

Why arrays: Every cell keeps its momentum and is pulled towards its neighbors in one expression; walls, slits and sources are just masks.

nxt ← damp × wall × ((2.0 × u) − p) + (c2 × ᵘl̲ap u) + drive
stencils by rotationmasksscalar extensionbroadcasting with table
Cellular automata lab Live

Cellular automata lab

Every rule is a lookup table: rotations turn each cell's neighborhood into a number and the number picks its next state. Wolfram's Rule 30, 90 and 110 with an editable 8-entry table; Life, Brian's Brain and Wireworld as editable state-by-neighbors tables.

Why arrays: Any rule is a lookup table, indexed for every cell at once by its state and its neighbor count.

ᵘl̲ook ← { tbl b → (1 + (9 × b) + ᵘc̲ount b) s̲elect tbl }
rotationlookup by s_electreduce over axesfunction power
Langton's ant Live

Langton's ant

Two rules, chaos, then a highway after about 10,000 steps. The ant is a one-hot mask and a direction: looking, flipping and moving are whole-array operations, and the same code would move a thousand ants.

Why arrays: The ant is a mask with a single 1: looking, flipping and moving are whole-board operations, so a thousand ants would take the same code.

step ← dy o̲-₁ dx o̲-₂ a
one-hot masksrotationreducefunction power
Abelian sandpile Live

Abelian sandpile

Drop grains on a grid and watch avalanches: every cell with 4 or more grains topples at once, round after round, until the pile settles into a fractal. Drop more at the center, anywhere you click, or one everywhere.

Why arrays: Toppling order does not matter, so every cell topples at once, as often as it can: h d_iv 4, four rotations to share it, a mask for the edge. One expression a round.

inside × (h − 4 × q) + g
rotationsmasksinteger divisionpower
N-body gravity Live

N-body gravity

Gravity between every pair of bodies at once, with no loops: the pairs' displacements form a cube, the cube gives every pair's pull, and one reduce sums them into accelerations. A figure-eight three-body orbit, a binary star with planets, a collapsing cluster, Kepler's ellipse.

Why arrays: Every pair at once: a table of differences is the N x N cube of displacements, and one reduce sums each body's pulls.

(ᵘp̲lane x '− t̲able x) c̲at ᵘp̲lane y '− t̲able y
broadcasting with tablereduce along an axisrank-3 arraysleapfrog integration
Fourier epicycles Live

Fourier epicycles

Any closed curve is a sum of circles turning at whole-number speeds: a heart, a star, or one you draw, traced by circles on circles. The discrete Fourier transform is two matrix products; one running sum rebuilds the curve from any number of circles.

Why arrays: The transform is an outer product of angles and two matrix products; a running sum along the circles gives every reconstruction at once, so the circles slider needs no recomputation.

re ← ((C '+ '× i̲nner x) + S '+ '× i̲nner y) ÷ f̲loat n
outer product (table)inner productgradescan along an axis
Image pipeline Live

Image pipeline

Blur, Sobel edges, a threshold and max-pooling on a picture, each an array program. Every 3 x 3 filter is the stack of the picture's nine shifted copies times a kernel, summed; edit the kernels and click a pixel to see its window times each one.

Why arrays: Every 3 x 3 filter is the picture's nine shifted copies times a kernel, summed: blur and edges are the same function.

ᵘf̲ilter ← { k x → '+ r̲/₁₂ (ᵘw̲indows x) × k 'l̲eft t̲able x }
rotation by a list of amountsrank-4 arraysreduce over two axesreshape for pooling
Stencils by macro Live

Stencils by macro

Image kernels written as pictures of numbers, turned into code by a macro library of our own when the program is expanded: blur, edges, sharpen, emboss and heat each cost exactly their nonzero numbers. See the call, what it expands to, and the result.

Why arrays: A kernel is data, but its zeros need not cost anything: a macro reads the numbers once, when the program is expanded, and writes one rotation per nonzero number, so the program is the unrolled stencil.

ᵘh̲eat ← { p → p + 0.2 × "0 1 0  1 -4 1  0 1 0" ˢt̲encil< "p" }
macro libraries (.xtlm)expansion (xetal expand)rotationspower
Unix pipes in X_eTaL: a terminal recording Live

Unix pipes in X_eTaL

cat, wc, grep, uniq, sort, head and tail as X_eTaL programs, chained with Unix pipes: xetalcat sample.txt | xetalgrep the | xetalsort | xetalhead -n 3. Each matches the real tool, byte for byte. Command line only.

Why arrays: Every character is numbered by its line (a running sum of newlines), so choosing lines is a mask and reordering them is a stable grade: no loop over lines in any stage.

sorted ← (g̲rade ln s̲elect rank) s̲elect t
text as arraysscangradecompressrotations