nenu-lang / functions
Stable

Functions

  • Write [ReturnType] fn name(Type parameter) { body }; the explicit return type comes before fn.
  • An omitted return type is inferred only when the function body supplies enough compatible evidence.
  • Every reachable path of a value-returning function must return a compatible value.

Function Syntax

code
1number fn splitAmount(number total, number people) {2  return total / people3}

The general form is [ReturnType] fn name[(parameters)] { body }. The function keyword is a lexer alias for fn, but public examples use the shorter canonical form.

Parameters Are Type-First

code
1string fn expenseLabel(string title, number amount, string? note) {2  string suffix = note ?? ""3  return title + " " + suffix4}
  • Write Type name, not name: Type.
  • Optional parameters use Type? name.
  • Arguments are positional and must match the parameter types.
  • Parameter names are lowercase locals inside the function body.

Return Inference

code
1fn balanceLabel(number balance) {2  if balance > 0 {3    return "owed"4  } else if balance < 0 {5    return "owes"6  }78  return "even"9}

All value-returning paths produce string, so the function’s effective return type is string. Callers use that inferred signature exactly like an explicit contract.

Implicit Tail Returns

code
1number fn add(number a, number b) {2  a + b3}

A final expression may supply a function’s return value without the return keyword. The expression—or every branch of a final if—must match the declared or inferred return type.

When To Write The Return Type

  • Write it when the public contract should be obvious at the declaration.
  • Write it when the only returned value is [], {}, or ? and inference has no element type.
  • Write it when the function is intentionally optional or returns a structural collection.
  • Keep it omitted for a small internal helper whose return type is immediate from concrete values.
code
1Expense[] fn noExpenses() {2  return []3}45Expense? fn noSelectedExpense() {6  return ?7}

Complete Return Paths

code
1string fn statusLabel(bool settled) {2  if settled {3    return "Settled"4  }5  return "Open"6}

The incomplete version has a reachable path with no return value and violates its string contract. A throw also terminates a path, so a validated error path does not need a later return.

Calling Functions

code
1share = splitAmount(expense.amount, member_count)2label = balanceLabel(balance)3clearDraft()

Calls always use parentheses. A value-returning call may appear in an expression. A void call is a statement. A trailing effect call is not automatically the function result; write return SomeApi(...) when the call result is the return value.

Common Mistakes

WrongCorrect
fn number splitAmount(...)number fn splitAmount(...)
fn splitAmount(total: number)fn splitAmount(number total)
def splitAmountfn splitAmount
func splitAmountfn splitAmount
Return incompatible types from different pathsReturn one compatible type on every value path.

Continue Learning