In 1999, the Mars Climate Orbiter burned up in the Martian atmosphere because one team calculated in pound-force-seconds while another expected newton-seconds. The unit was lost in the handoff, and no compiler was there to catch it.

Makers live with a smaller version of that same failure every time a microcontroller is involved. Wiring up a servo, a sensor, or a stepper motor means reasoning in milliseconds, microseconds, degrees, radians, volts, and amps — and getting one of them wrong does not throw an exception. It snaps a belt, stalls a motor, or fries a component.

Lale is an open-source systems language that puts physical units directly in the type system, so mistakes like that are caught at compile time instead of on the workbench:

var distance as f64 in <m> = 0.5
var time    as f64 in <s> = 2.0

var speed as f64 = distance + time   // ❌ compile-time error

The compiler refuses to add a length to a duration. Radians are not degrees, and it will not quietly pretend they are.

That is a genuinely useful property for someone who builds things. But I want to be honest about when you can rely on it.

What is real today

The unit safety is not a slide in a pitch deck. It is implemented and working in the current compiler:

  • Compile-time dimensional analysis. Units are inferred from expressions and checked against declared types. A mismatch is a compile error.
  • Runtime assertions for the cases the compiler cannot settle. If an exponent is only known at runtime, the compiler emits a check rather than silently dropping the unit. These assertions are on in all builds, not just debug.
  • Explicit safety. Lale has no implicit type conversions and no silent narrowing. If a conversion is allowed at all, you have to write it.
  • No exceptions. Control flow stays visible and deterministic — no hidden stack unwinding — which matters when you are reasoning about what a small device does at every step.
  • A customizable output hook. The compiler's error path already accounts for embedded systems: the write hook can be redirected to a UART instead of stderr.

So the discipline a maker needs — catching unit slips, forcing explicit conversions, keeping control flow visible — is available today.

What is not real yet

Lale is at version 0.1.0. The language is not yet at 1.0, and the roadmap is explicit about where the embedded story lands:

  • The concurrency and memory model is version 5.0.0.
  • The first reference microcontroller target is version 6.0.0.

That means you cannot flash a Lale program onto an Arduino-class board today, and you should not port firmware to it. The path from "compiles on my laptop" to "runs on bare metal" is still ahead of the project.

The honest pitch

This is not a claim that Lale is ready to replace C on your next board. It is a bet on the future, and a realistic one to start paying into early.

The valuable part — the habit of writing unit-correct, explicitly-safe control code — is something you can adopt now, on a desktop, long before the embedded target ships. Write your motor math and your sensor timing logic in Lale, let the compiler catch the unit slips you would otherwise find the hard way, and the habits transfer when version 6.0.0 arrives.

If that sounds like a long time horizon, it is. But the bug it targets — the Mars Climate Orbiter class of mistake — is not going away, and no amount of careful commenting catches what a compiler can check for free.

We would rather be honest about the timeline than oversell a tool that is not finished. The unit safety is real today. The hardware is on the way.