A programming language

>lux

A small language built to be a great first one, and then to be outgrown.

~/crawl
$ lux run world.lux

THE LITTLE KEEP

You stand at the mouth of an old stone
keep. Cold air drifts from a passage north.

(type help for commands)

north
A wide hall, its banners long rotted. Ways
lead south and east, and a heavy door faces
north.
A brass key lies on the dusty floor.
A locked iron door blocks the way north.

take key
You take the key.

Most first languages are big. You spend your early weeks stepping around the parts you are not ready for, and the parts you are ready for arrive wrapped in ceremony you cannot yet read.

lux takes the opposite bet. It is small enough to count: fourteen keywords, and that is all of them. Go has a reputation for being a small language, and Go has twenty-five keywords.

What fourteen buys is still the whole shape of a real language — variables and arithmetic, strings, if and while, functions and recursion, for ... in over ranges and arrays, your own types as structs and enums, and pattern matching that you are made to finish. There is no null — a value that might be missing is an Option, and one that might fail is a Result — so the two situations that sink beginners are ideas you handle rather than traps you fall into.

The hard things left out — ownership, classes, goroutines — are the ideas the bigger languages are built around, and they land far better once you have written something that needs them. Leaving them out is not hiding them. It is drawing a line at the edge of what a first language should carry, and then handing over the map across it. Every feature in lux is the simplest version of an idea you meet again in Rust, Swift, and Go, which is why lux convert can print your program as any of the three and you will recognize every line of it.

What you are actually learning is not lux. It is how a computer holds a value, chooses between two things, and admits an answer might be missing — and that is worth having whether you go on to Rust, or stop after a few evenings and never write another line.

func greet(name: string) {
    print("Hello,", name)
}

greet("world")

Learn it, build with it, outgrow it

lux is meant to be walked through and then left behind, so everything written about it is a route rather than a pile of reference. Here it is, in order. Each piece stands on its own, so you can join wherever you are.

You do not have to finish it. Every stage pays on its own — an hour with the first one leaves you knowing something true about how a computer works, whether or not you ever open the second.

  1. Learn the shapes

    An Introduction to Programming starts from nothing at all: variables, decisions, loops, functions, your own types, and how to read an error instead of fearing it. About an hour, and every example on the page runs.

    The same ground is inside the binary as lux learn, one short card at a time, with more on any card for the deeper why and the name the rest of the world uses. When a program does something you did not expect, lux trace runs it again and narrates every line as it goes.

  2. Build a world

    lux crawl writes a small, playable text adventure into a folder — rooms, a locked door, a torch in the cellar, all of it in one world.lux that is yours to open and change. It is the first step from using a program to building one.

    Building Your Own Keep takes that file apart and hands it back: how a single turn works, where to skip to the part you are building, and three exercises that add a room, hide something to find, and teach the world a new rule. lux magic keeps the working shapes within reach while you build.

    When editing somebody else's world stops being the interesting part, Starting Something of Your Own is the jump to a blank file: sizing an idea down until it is finishable, saying what it does before writing it, working out what it has to remember, and growing it one runnable piece at a time. It builds a small program from nothing in front of you. When you want to see what fits inside a language this size, luxplay is a folder of programs written in lux for the fun of it — games, puzzles and small demonstrations, several of them shaped by something the language deliberately leaves out.

    Something you write will not work, and probably quite soon. When It Doesn't Work is how to find out why: reading what lux tells you and where the arrow really points, watching a program go by one line at a time with lux trace, cutting it down until the bug is the only thing left, and the handful of wrong answers nothing warns you about at all.

  3. Outgrow it

    One day the language runs out, and that day is the point. It arrives in more than one way. Some people move to a bigger language and keep writing code. Some stop at the moment they can see why the walls were put where they are. Some never write another program and keep the way of thinking anyway. All three are the language finishing its job.

    When lux Feels Small is how to tell that is where you are, what carries over, what is genuinely new, and how to choose what comes next.

    Then read the keep you already wrote in the language you picked. Your Keep in Swift is the shortest, because Swift is the closest — your Option<Room> becomes Room?. Your Keep in Go goes somewhere plainer and faster, where your enum becomes an interface and your Option disappears entirely. Your Keep in Rust is the longest: Rust keeps every guarantee lux gave you, then asks the one question lux never made you answer, about who owns a value and what happens when somebody else wants it.

Install it

macOS and Linux

curl -LsSf https://anderix.com/lux/install | sh

Paste that into a terminal and you are done. Later on, lux update fetches the newest release and replaces this copy in place.

Windows

irm https://anderix.com/lux/install.ps1 | iex

The same installer and the same releases, in PowerShell. A running lux.exe cannot overwrite its own file, so lux update hands you the line to paste into a fresh terminal instead of doing it for you.

Have Rust already? cargo install luxc works too. That copy belongs to cargo rather than to the installer, so lux update prints the upgrade command for wherever the binary actually came from — the same goes for any package manager you install it through. It will not quietly put a second lux somewhere else and leave your PATH to decide which one answers.

Nothing else to download. The tutorial, the reference, and the adventure all travel inside the binary, and the error messages point at the card that explains them, so you meet an idea at the moment you need it. When you want the whole thing at once, lux learn tour runs the language past you top to bottom, every feature with an example that runs — about a fifteen-minute read.

lux learn               # the menu of topics
lux learn enums more    # one idea, deeper
lux learn tour          # the whole language, top to bottom
lux crawl               # a world to play and change
lux run world.lux       # interpret a program
lux build world.lux     # compile it to a native binary

Four runtimes, one output

What you write in lux is a working program from the first run, and it travels. The keep that lux crawl writes is 330 lines. Converted to Rust, Swift, and Go, compiled, and walked through the same fourteen commands, all four runtimes produce the same 118 lines of output — not similar, identical. That is an easy thing to claim and an easy thing to fudge, so it gets checked rather than asserted.

$ for r in "lux run world.lux" ./keep-rust ./keep-go ./keep-swift; do
>     rm -f the-secret.txt
>     $r < walk.txt | md5sum
> done

eca1931e9fd0fe561a54e301d4c48202  -
eca1931e9fd0fe561a54e301d4c48202  -
eca1931e9fd0fe561a54e301d4c48202  -
eca1931e9fd0fe561a54e301d4c48202  -

The agreement runs one step further back than the output. lux checks your program's types before it runs a line of it, on every branch — including the ones that did not happen to run this time — so a mistake is caught in lux's own words rather than surfacing later as a complaint from a compiler about code you never wrote.

That is the promise underneath the whole thing. What you learn here is not a dialect of nothing — it is the shared middle of three languages worth moving on to, and the translation is close enough that the same program keeps its behavior all the way across.

That is also the evidence. You can check for yourself that what you learned was not a trick of this language, because here it is working in three others.