Philosophy on Simplicity, Safety, and Elegance
Every design decision in Luma is guided by three principles: simplicity, safety, and elegance. This page explains what these mean in practice and how they shape the language.
Simplicity
If a feature requires a paragraph to explain, it’s too complex.
Luma deliberately stays small. The entire language can be learned in a weekend. This isn’t a limitation; it’s a feature.
Simplicity in practice:
- One way to iterate:
.walk()works on lists, sets, maps, ranges, and files. Nofor,while,do,foreach, orloopkeywords to choose between. - One way to declare variables:
name: type = value. Always the same pattern. - No hidden behavior: What you write is what happens. No implicit conversions (except safe int-to-float promotion), no magic methods, no operator overloading.
- Small keyword set: The entire language uses fewer than 20 keywords.
The goal is not to limit what you can do, but to make sure everything you do is immediately understandable.
Safety
The compiler should catch mistakes before the program runs.
Luma’s type system exists to protect you, not to burden you.
Safety in practice:
- Optional types (
?T) make nil explicit. You can’t accidentally use a nil value because regular types cannot be nil. - No truthiness:
if countdoesn’t work. You must writeif count > 0. This eliminates an entire class of bugs where values are accidentally treated as booleans. - Explicit type annotations: Every variable declaration states its type. You always know what you’re working with.
- Safe conversions:
"abc".to_int()returnsnil, not a crash."abc".to_int(0)returns a safe default. - Immutability with
lock: When a value shouldn’t change, say so:lock pi: float = 3.14159.
Safety doesn’t mean ceremony. It means fewer surprises at runtime.
Elegance
Code should be pleasant to read and pleasant to write.
Elegance is the hardest principle to define, but you recognize it when you see it. Elegant code communicates its intent clearly without wasted syntax.
Elegance in practice:
- String interpolation:
"Hello ${name}"instead of format functions or concatenation. - Expression bodies:
fn double(x: int) -> int => x * 2for simple functions. - Inline walk:
nums.walk(n) -> print(n)for one-line iterations. - Clean struct syntax: Fields are declared simply, constructors are automatic.
- Composable APIs:
json.decode(file("config.json").read())reads naturally as a sentence.
Luma avoids the temptation to add features just because they’re popular. Every addition must earn its place by making code clearer, not just shorter.
These principles in tension
Sometimes these principles pull in different directions:
- Adding type annotations is less simple but more safe
- Optional types add complexity but prevent crashes
- Requiring explicit comparisons is more verbose but eliminates ambiguity
When principles conflict, Luma chooses the option that helps the programmer understand their code better. A few extra characters are worth it if they prevent confusion.
The result
A Luma program reads almost like pseudocode. A beginner can look at it and understand what it does. An experienced programmer can write it quickly without fighting the language. That’s the goal: a language where simplicity, safety, and elegance work together instead of against each other.