Luce
Luce BaseSourceLuciaOS

7. Functions

7.1 Declaration#

func area(width: float, height: float = 1.0) -> float:
    return width * height

func log(message: str):
    print(message)

Parameters are let bindings. A result type after ->; none means unit. A default is a constant expression or a constructor of one. Every path through a function with a result returns a value; the compiler proves it. A function may be recursive.

7.2 Calls#

let a = area(2.0, 3.0)
let b = area(width = 2.0)
let c = area(2.0, height = 3.0)

Arguments are positional, then named; a named argument names a parameter once; a parameter with a default may be omitted. There is no overloading and no variadic parameter; a function that wants any number of things takes a list.

7.3 Methods#

A function declared inside a struct, enum or class is a method; its receiver is self. A method of a struct that assigns to a field of self is a mutating method, and may be called only on a var; the compiler infers this, nothing is written. A method of a class may always assign to var fields. A function declared inside a type without self in its body and called through the type, Point.origin(), is a type function.

7.4 Function values, lambdas and closures#

let positive: func(int) -> bool = (n) => n > 0
let doubled = numbers.map((n) => n * 2)

let counter = func () -> int:
    count += 1
    return count

A named function, a method bound to a receiver, and a lambda are values of a function type. (params) => expression is an expression lambda whose parameter types come from the expected function type; func (params) -> R: with a suite is a block lambda with everything written. A lambda that refers to an outer local captures it: a let value is copied, an object is shared, and a var becomes one cell shared by the scope and every closure that captures it, so a captured counter counts. Closures may be stored, returned and passed anywhere a function value is expected, and live as long as the last reference to them.

A nonfallible function value converts to a function with identical parameters and a fallible result, func(A) -> T to func(A) -> T!. A retained adapter invokes the original callback and returns success; captured cells and receivers keep their normal lifetimes. The opposite conversion is rejected. Fallibility of a block lambda comes from its own written result; an expression lambda uses its expected function type.