Book
Binds and functions
When to pick $, ~, or #, and how free functions work as values.
Choosing a bind
Most names should stay fixed. $ makes that the default. ~ is for loops, accumulators, and reassigned handlers. # is for values that must exist before runtime: table sizes, version strings, pure chains of other constants. If a “const” needs a function call, bind it at runtime with $ or ~, not #.
Bind leaders
$ is immutable at runtime. ~ is mutable (~ name = updates). # is compile-time only: literals and ops on other # names. Runtime calls are outside constant expressions.
Functions are values
A free function is a bind whose value is a function expression. ^ returns from the current function. Bare ^ is none in option-shaped functions.
/ std/io
/ std/str
# A = 21
# B = A + A
$ add = (a, b) {
^ a + b
}
io.print(str.from_int(B))
io.print(str.from_int(add(20, 22)))Compose with callables
Because a function is a value, higher-order code needs no separate declaration or interface. Pass the callable as an argument and call the parameter normally. Methods stay members invoked through a receiver.
$ apply = (f, value) {
^ f(value)
}
$ increment = (value) {
^ value + 1
}
$ answer = apply(increment, 41)Names and shadowing
Names are introduced once per region. Shadowing is rejected. Rebind mutables with ~.