Scarlet Industries

Syntax

Bindings, blocks and functions. Almost everything is an expression, and nothing mutates.

Bindings

A binding is name = expression. Bindings are immutable. Rebinding a name shadows the earlier one from that point on. An annotation goes between the name and the =, and it is documentation the compiler checks, not information it needs: types are inferred at their most general.

units = 4
units = units + 2
restock Int = int.max(units * 2, 12)

(total, saved) = price_line(unit_cents, units)

Almost everything is an expression. if yields a value, and so does a { ... } block. There is no return: a function's value is its body's last expression. Parentheses build tuples; braces group.

Functions

fn name(params) ReturnType { body } declares a function. Parameter types are written after the name. A lambda is fn(x) body and carries no return-type slot. A closure captures the value a name holds when the closure is made; rebinding the name afterwards does not reach back into the closure.

/** Returns a function that adds `k`. The returned closure carries `k` with it. */
fn adder(k Int) fn(Int) Int {
	fn(x) x + k
}

pub fn main() {
	base = 10
	add_base = adder(base)
	base = 100
	println('add_base(1) = ${add_base(1)}, base is now ${base}')
}