Functions
An ordinary function declaration has a name, typed parameters, a result type, and a body:
func name(parameter : Type) -> ResultType do bodyendEvery value parameter and result has an explicit type. Local bindings inside the body may be inferred.
Return a tail expression
Section titled “Return a tail expression”The final expression of the body is the normal result:
func add(left : Int, right : Int) -> Int do left + rightendIf the body ends after a semicolon-terminated statement, it produces Unit:
func greet(name : String) -> Unit do Console.println("Hello, " ++ name ++ "!");endCall a function
Section titled “Call a function”A call supplies one positional argument per positional parameter:
func area(width : Int, height : Int) -> Int do width * heightend
func main() -> Unit do result = area(6, 7); Debug.trace(result);endThe callee is evaluated first, then arguments from left to right. Each argument is evaluated exactly once.
Required named parameters
Section titled “Required named parameters”Question parameters provide named inputs. Their basic form is a trailing
?{...} group in the declaration and call:
func rectangle(?{width: Int, height: Int}) -> Int do width * heightend
func main() -> Unit do area = rectangle(?{height: 7, width: 6}); Debug.trace(area);endAnswers are matched by name, so callers may write them in any order. Every required answer must be present exactly once and have the declared type. Positional arguments, when a function has both forms, come before the question answer group.
Defaults, presence questions, compiler-filled source locations, and contextual capability parameters build on this syntax. Learn those forms in Question parameters.
Return early
Section titled “Return early”Use return value; to leave the current function before its tail expression:
func clamp_nonnegative(value : Int) -> Int do if value < 0 then return 0; end; valueendA bare return; is valid only when the function result is Unit.
Recursion
Section titled “Recursion”A top-level function may call itself, and functions in the same source file may refer to declarations written later:
func factorial(value : Int) -> Int do if value <= 1 then 1 else value * factorial(value - 1) endend
func main() -> Unit do Debug.trace(factorial(5));endUse recursion when the problem is naturally recursive. For ordinary counting or accumulation, a loop usually makes the evolving state and exit conditions easier to inspect.
Local functions
Section titled “Local functions”A named local function can organize a helper that belongs only to one outer function:
func sum_to(limit : Int) -> Int do func loop(current : Int, total : Int) -> Int do if current == limit then total else loop(current + 1, total + current) end end; loop(0, 0)endLocal functions are recursively bound. Mutually recursive local functions are written as one comma-separated function group.
Function values and lambdas are covered later in Higher-order functions.
Next: control flow.