Higher-order functions
You do not need function values to complete the Language basics path. Reach for them when an algorithm should receive behavior as data, return a configured operation, or build a reusable transformation pipeline.
Function types
Section titled “Function types”A function type lists its parameter types and result:
(Int) -> String(Int, Int) -> Int() -> UnitParameter names may be included as documentation, but they do not affect type identity:
(value : Int) -> StringPass a function
Section titled “Pass a function”A parameter with a function type accepts a named function or lambda with the same boundary:
func apply_twice(transform : (Int) -> Int, value : Int) -> Int do transform(transform(value))end
func increment(value : Int) -> Int do value + 1end
func main() -> Unit do Debug.trace(apply_twice(increment, 10));endThe function value is called with ordinary call syntax. Arguments and results are still checked statically.
Lambdas
Section titled “Lambdas”A lambda is an anonymous function expression:
func apply_twice(transform : (Int) -> Int, value : Int) -> Int do transform(transform(value))end
func main() -> Unit do doubled = apply_twice(|value : Int| value * 2, 3); Debug.trace(doubled);endLambda parameter annotations may be inferred when the expected function type already determines them. Add the annotation when the surrounding expression does not provide enough information or when it makes the boundary clearer.
Closures capture lexical bindings
Section titled “Closures capture lexical bindings”A lambda may capture a value from its defining scope:
func make_adder(amount : Int) -> (Int) -> Int do |value| value + amountend
func main() -> Unit do add_three = make_adder(3); add_ten = make_adder(10); Debug.trace(add_three(7)); Debug.trace(add_ten(7));endEach returned closure retains its own amount. Capturing a mut local shares
that mutable storage location; capturing an ordinary binding retains its value.
Return and compose functions
Section titled “Return and compose functions”Function values can be combined like other values:
func compose( outer : (Int) -> Int, inner : (Int) -> Int,) -> (Int) -> Int do |value| outer(inner(value))end
func main() -> Unit do add_two : (Int) -> Int = |value| value + 2; triple : (Int) -> Int = |value| value * 3; transform = compose(triple, add_two); Debug.trace(transform(4));endLambdas are anonymous and do not become recursive merely because they are stored in a binding. Use a named local function when recursion is required.
Generic higher-order functions remove the fixed Int boundary used here.
Continue with Generic programming.