Learnable math. A small language where math reads the way you read — left to right, no tables to memorize. Learn the whole thing in five minutes, right in a browser tab.
Open the playground and follow along. Every box below is live — hit run to open it, then poke at it.
Fluent runs left to right, the way you read. No precedence tables, no acronyms. Want a piece to go first? Glue it — hug the parts together with no space. Or, you know. Parens.
(
1 + 2 * 3, ; 9 — spaced, straight left to right
1 + 2*3, ; 7 — glue the * and it goes first
1 + (2 * 3), ; 7 — or, you know. parens
)Not sure how a line will group? Drop it in backticks and Fluent draws it as a tree — you see exactly how it flows. Hover the nodes; the shape you see is the order it runs.
`1 + 2*3`A list of numbers goes in square brackets — and acts like one number. Do the math to the whole list at once; reach inside with a spaced _, where _ 0 is the 0th item (Fluent counts from zero).
(
[1, 2, 3] + 10, ; [11, 12, 13] — the 10 lands on each
[10, 20, 30] _ 0, ; 10 — the 0th item
[10, 20, 30] _ 2, ; 30 — and the 2nd
)Need a run of numbers? 1 ... 5 counts from 1 through 5.
1 ... 5 ; [1, 2, 3, 4, 5]Name anything with a :. Then reuse the name as often as you like.
(
v: [1, 2, 3],
v + v ; [2, 4, 6] — name once, use twice
)Every built-in has three names — a long one to discover, a word for habit, a glyph for speed. TensorSum is sum is Σ: all the same function. Hover any name and its doc card pops up, right in the editor — all three open the same card. Spell it out while you're learning; shrink it to the glyph once it's muscle memory.
(
TensorSum([1, 2, 3]), ; 6
sum([1, 2, 3]), ; 6 — same function, shorter name
Σ(1...3), ; 6 — same function, just a glyph
)▶ run · (the full list of names)
Operators aren't a special club. + is really just a function — so you can call it by name, or name your own. Even an emoji works.
(
1 + 2, ; 3
add(1, 2), ; 3 — + is really a function, called add
+(1, 2), ; 3 — so you can call it like one
1 add 2, ; 3 — or put its name in the middle
🐱: add, ; name your own operator...
2 🐱 3, ; 5 — ...even an emoji
)Want it to move? Wrap a value in $( ) and it comes alive — everything that touches it recomputes when it changes. No render loop, no state to wire up. Drag the slider.
(
x: $(0.5),
Slider(x),
0 ... 100*x
)And there's no print. Every value just shows itself — a row of numbers becomes a plot, a grid becomes an image, quoted code becomes that tree from before.
[0, 1, 4, 9, 16, 25, 16, 9, 4, 1, 0]That's the whole idea. Here's what people build with it.
| demo | ||
|---|---|---|
| 🌀 | Mandelbrot — the Mandelbrot set over the whole plane, sharper as you drag the depth | ▶ run |
| 🦠 | Game of Life — Conway's Game of Life on a large grid | ▶ run |
| 🔮 | The Name Dreamer — a small transformer that invents new names from a word list | ▶ run |
| 🐦 | Combinators — combine functions without naming their arguments | ▶ run |
| 📷 | Live edge detection — your webcam, edge-detected in real time | ▶ run |
| 🎵 | Live spectrum — your microphone's frequency spectrum, live | ▶ run |
| 🎸 | Pitch detector — the pitch of a note you hum | ▶ run |
| 📈 | Linear regression — a line fit to points by gradient descent | ▶ run |
| 🏔 | Touch the loss landscape — a ball you roll downhill on a loss surface | ▶ run |
| ⚔️ | adam vs sgd — two optimizers descending the same surface from the same start | ▶ run |
| 🌸 | Reaction–diffusion — two reacting chemicals that settle into spots and stripes | ▶ run |
| 🔬 | Lenia — smooth, continuous cellular automata | ▶ run |
| 🧲 | Spinning magnets — an animated vector field | ▶ run |
More in the playground: press Ctrl+O for the full gallery.
The tour stops at the basics; the language keeps going. ∇ differentiates any function you built from smooth numeric ops — reshape and indexing included — and nests, so ∇(∇(f)) is the second derivative. ~ makes a trainable variable and an optimizer (sgd, adam, adamw, adagrad) minimizes a loss; ⟳ runs the loop between frames so the UI stays live. That's the whole of the linear-regression and Name Dreamer demos above.
θ: ~([0, 0]),
𝓛: { Σ((θ - [0.23, 0.47])^2) },
opt: sgd(0.1),
{ opt(𝓛) } ⟳ 100,
θThen hover any built-in for its docs, or open the built-in Documentation for the full tour.
the names, at a glance
| glyph | word | full name |
|---|---|---|
∇ |
grad |
TensorGradient |
Σ |
sum |
TensorSum |
Π |
prod |
TensorProduct |
μ |
mean |
TensorMean |
⌈ |
ceil |
TensorCeil |
⌊ |
floor |
TensorFloor |
| — | max |
TensorMax |
| — | min |
TensorMin |
# |
length |
TensorLength |
_ |
gather |
TensorGather |
⍴ |
reshape |
TensorReshape |
..< |
range |
TensorRange |
... |
— | TensorRangeInclusive |
⊗ |
outer |
TensorOuter |
^ |
pow |
TensorPower |
√ |
root |
TensorRoot |
% |
mod |
TensorRemainder |
÷ |
div |
TensorDivide |
× |
mul |
TensorMultiply |
~ |
var |
TensorVariable |
:= |
— | TensorAssign |
⟳ |
iter |
FunctionIterate |
⍣ |
— | FunctionPower |
. |
apply |
FunctionApply |
@ |
eval |
FunctionEvaluate |
$ |
— | Reactive |
| — | watch |
TensorWatch |
| — | conv |
TensorConvolution |
| — | once |
SignalOnce |
Some cells are still empty — the language is young, and names are earned.
Live evaluation on every keystroke, hover docs, unicode completion (type alpha, get α), syntax trees for quoted code, camera and microphone as tensor sources, and LLM code generation — write ;;a bouncing ball;; and it appears (bring your own Anthropic API key, set via the command palette).
Ctrl+O examples · Ctrl+S share as URL · Ctrl+P commands · Ctrl+Space complete — Safari reserves ⌘O, use ⇧⌘O there
git clone https://github.com/mlajtos/fluent.git
cd fluent && bun install
bun dev # → http://localhost:3000The whole thing fits in a handful of files — read it, change it:
| file | what |
|---|---|
language.ts |
the language — grammar (Ohm), evaluator, prelude; tensors via jax-js, reactivity via preact signals |
client.tsx |
the IDE — components, visualizers, Monaco editor, playground |
tests.ts |
language tests (bun test ./tests.ts) |
tests.browser.ts |
IDE tests in real Chromium (bun run test:browser) |