Functions & Lambdas
A function names a piece of computation; a lambda is the anonymous version of the same thing. Both share the same call shape and the same parameter conveniences — defaults, named arguments, irrefutable destructuring — and both slot interchangeably into pipes and higher-order code.
Defining a function
Section titled “Defining a function”fn name(params): ReturnType { body }. The body is a block expression: its
last expression is the return value — no return keyword needed for the
happy path. return exists for early exits from inside a conditional:
fn add(x: Int, y: Int): Int {
x + y
}
fn abs(x: Int): Int {
if x < 0 { return -x }
x
}
fn main(): Int {
dbg add(3, 4)
dbg abs(-9)
}
Lambdas
Section titled “Lambdas”Lambdas are written |params| body. Annotate parameter types when there’s no
other clue; otherwise let inference handle it. A lambda is a first-class value
— bind it to a name, pass it to another function, or return one.
fn main(): Int {
inc = |x: Int| x + 1
dbg inc(41)
}
Named functions are first-class too: f = add binds the value of add to f,
and f(3, 4) works exactly like add(3, 4).
No Function Overloads
Section titled “No Function Overloads”Within a scope, a function name has one meaning. Nomi does not choose between multiple same-named functions by argument type:
type UserId String
fn parse(text: String): Int {
0
}
fn parse(id: UserId): Int {
0
}
fn main() {
Unit
}
Use names that describe the conversion or construction path:
Int.parse(text), Date.parse(text), Date.from_parts(...),
String.from_codepoints(...). For polymorphism, define an interface and
implement it for each type; dispatch is explicit at the call site with a type
or interface qualifier.
Default parameter values
Section titled “Default parameter values”Any parameter — in a function or a lambda — can carry a default. Callers can omit it, or pass a value to override.
fn greet(name: String, greeting: String = "Hello"): String {
"${greeting}, ${name}!"
}
fn main(): Int {
dbg greet("World")
dbg greet("World", "Hi")
// Lambdas take defaults the same way:
add = |x: Int, y = 10| x + y
dbg add(5)
dbg add(5, 2)
}
Named arguments
Section titled “Named arguments”Any parameter can be passed by name at the call site, in any order. Positional and named arguments can mix — positional first, then named. Named arguments make defaulted middle parameters easy to override without remembering positions:
fn connect(host: String, port: Int = 8080, timeout: Int = 30): String {
"${host}:${port}:${timeout}"
}
fn main(): String {
dbg connect("localhost")
dbg connect("localhost", timeout: 10)
dbg connect(host: "api", port: 443, timeout: 5)
}
Destructuring parameters
Section titled “Destructuring parameters”A function or lambda parameter can take any irrefutable pattern in place of a plain name — tuple, anonymous struct, distinct-type wrapper, single-variant enum. The pattern unpacks the argument on the way in.
A pattern whose head names a concrete type (a distinct constructor like
Dur(...), a typed struct like Point{...}) is self-typing — the type is
in the pattern, so no : Type annotation needed. A type-less pattern (a plain
tuple, an anonymous struct) needs the annotation:
type Dur Int
struct Point {
field x: Int
field y: Int
}
fn subtract(Dur(a), Dur(b)): Dur {
Dur(a - b)
}
fn sum_point(Point{x, y}): Int {
x + y
}
fn add_pair((a, b): (Int, Int)): Int {
a + b
}
fn main(): Int {
Dur(diff) = subtract(Dur(10), Dur(3))
dbg diff
dbg sum_point(Point{x: 4, y: 5})
dbg add_pair((20, 22))
}
Trailing lambdas
Section titled “Trailing lambdas”When a function’s last parameter is a lambda, the call site can leave the lambda unnamed at the end and it routes into the last slot automatically — even when middle defaulted parameters are overridden by name. The pattern keeps callback-style functions readable:
fn transform(x: Int, factor: Int = 1, f: (Int) -> Int): Int {
f(x * factor)
}
fn main(): Int {
dbg transform(5, |x| x + 1)
dbg transform(5, factor: 3, |x| x + 1)
}
The next chapter — Pipes — shows how |> weaves everything in this
chapter into expressions that read top-to-bottom.