Function

A function is a callable symbol.

Type checking MUST happen at the function boundaries, meaning:

Functions can be marked as tail-recursive. Such functions MUST be unrolled as a loop to avoid stack overflows.

Tail-recursive functions MUST return either:

Syntax

function_definition
func tailrec [ signature ] { pattern_matching_clause , , }
Show source
function_definition
  = ("func" / "tailrec")
  "[" signature "]"
  "{" pattern_matching_clause ("," pattern_matching_clause)* ","? "}"
signature
( type_expression , , ) -> type_expression
Show source
signature
  = "(" (type_expression ("," type_expression)* ","?)? ")" "->" type_expression

Example

let natural: class[int] {
  (n) -> n >= 0,
};

let factorial_impl: tailrec[(natural, natural) -> natural] {
  (0, acc) -> final[acc],
  (n, acc) -> recurse[n - 1, n * acc],
};

let factorial: func[(natural) -> natural] {
  (0) -> 1,
  (1) -> 1,
  (n) -> factorial_impl(n, 1),
};

Semantics

The return value of a function MUST be the value the matching clause evalutes to.

For tail-recursive functions, the return value MUST be the value passed with final[...].