Skip to content

Functions

Humbat edited this page Oct 11, 2026 · 2 revisions

Functions (Dual Syntax)

Tera supports both traditional multi-line function blocks and concise inline lambda-style declarations.


1. Standard Block Functions

For multi-line logic, Tera uses a traditional block structure that explicitly defines the return type using the arrow operator[cite: 1]:

fn add(a: int, b: int) => int {
    return $a+b$;
}

2. Inline Expression Functions

For rapid, concise operations, Tera supports inline lambda-style function declarations:

let add: (a: int, b: int) => (a + b) => int;

3. Function signatures

Function declarations now carry a real signature — parameter names, parameter types and a return type — and every call site is checked against it.

fn add(a: int, b: int) => int {
  return a + b
}

Internally the signature is a type string such as fn(int,int)->int (or fn(int,string)->bool), which is what the call checker compares against.

What is checked

Check Error
Wrong argument count [Type Error] Function expects 2 argument(s) but got 1.
Wrong argument type [Type Error] Argument 2 expects type 'int' but got 'string'.
Wrong returned type [Type Error] Cannot return value of type 'string' from a function declared to return 'int'.
Calling a non-function [Type Error] Cannot call non-function target of type 'int'.

Return types propagate to callers

A call expression is typed as the function's declared return type, so results can be used wherever that type is expected.

fn square(n: int) => int {
  return n * n
}

fn isEven(n: int) => bool {
  return n % 2 == 0
}

// the result of square() is an int
let area: square(4) => int
print("area =", area)          // area = 16

// the result of isEven() is a bool, so it works as a condition directly
if (isEven(10)) {
  print("10 is even")
}

// and as a value assigned into an int array
let xs: [1, 2, 3] => arr[int]
xs[0] = square(3)
print("xs =", xs)              // xs = [ 9, 2, 3 ]

Anonymous function expressions are checked the same way:

let mul: fn(a: int, b: int) => int {
  return a * b
}
print("mul(4, 5) =", mul(4, 5))   // mul(4, 5) = 20

What changed for functions

The => <type> clause is not new — it was already required by the grammar. What changed is that the declared signature is now recorded and enforced:

Before After
A named function was typed simply as function typed as fn(int,int)->int
Argument count never checked checked
Argument types never checked checked
A call's result was typed undefined typed as the declared return type
A return value was not checked checked against the declared return type
break/continue inside a function body leaked into the caller's loop context loop context is reset at the function boundary

Clone this wiki locally