Use return to send a value back to the caller.
double |value Int| -> Int:
return value * 2
;
A function can return more than one success value:
pair || -> String, Int:
return "Ana", 2
;
name, count = pair()
The number of receiving names must match the number of returned success values.
Functions that can fail add one final error return marked with !. The Errors page explains how to propagate or recover from that path.
return produces the success values declared by a function.
double |value Int| -> Int:
return value * 2
;
Success returns
- Return values must match the declared success-slot count.
- Each return value must be compatible with its corresponding slot type.
- A function with required success values must return or otherwise terminate on every reachable path.
- A function with no success slots may reach the end of its body.
return with no values can leave a no-success function early.Void is not an explicit return-slot type.
Multiple success values
A function may declare and return more than one success value.
pair || -> String, Int:
return "Ana", 2
;
name, count = pair()
The receiving multi-bind must match the success arity.
Multiple return values are not a user-visible tuple value. A normal single-target declaration cannot receive a multi-return call.
Value-producing if, full matches and catch blocks can also satisfy multi-value receiving sites when every producing path has the required arity.
Error slot shape
A function signature may contain at most one error-channel slot marked with !.
That slot must be last.
load |id String| -> String, Error!:
if id.is_empty():
return! Error("Missing id")
;
return "value"
;
return!, postfix propagation and catch are documented by Errors, options and assertions.
Return contract
Return slots contain types and channels only. Source code has no borrowed, owned, move or parameter-alias return annotation.
Returning an existing value follows ordinary shared-reference semantics. The compiler infers freshness and alias effects from validated bodies and calls. Public interfaces may carry those inferred summaries. External bindings may carry explicit compiler-owned alias metadata because their foreign bodies are unavailable.
The alias and freshness summary lattice is compiler-owned semantic information. It is not source syntax, a source type or a signature category.
Binding freshness and allocation identity
Every function result enters a fresh caller binding. This does not imply a fresh allocation. Returning an existing record, collection, map, string allocation, opaque handle or projection preserves its allocation identity and lifetime owner. The result binding never points at the callee's parameter or local binding slot.
Reassigning one binding does not rebind another binding that received the same allocation through a return. The allocation remains alive while any legal alias retains it.
Ordinary return does not copy. Use copy when the caller needs an independent result graph.
The compiler's inferred alias summary governs borrow and lifetime validation. It does not change the source type and does not select a binding-reference return ABI.
External alias metadata describes whether a foreign result aliases an argument allocation. It does not expose binding references to source code and does not allow host code to return a Moth binding cell.
Fallible and multiple returns
A fallible carrier is fresh while its success payload may alias a parameter allocation. Multiple return values may alias parameters or each other. Each returned value enters its own caller binding. Runtime lowering preserves those allocation relationships.