Callables
Callables are function values. They are Thread-Stack-managed: referencing a function allocates its frame on the heap and stores a pointer to the function in front of it.
The fn Type
// no params, no return
fn[() -> void]
// two params, one return
fn[i32, i32 -> i32]
// multiple returns: no parens
fn[i32, i32 -> i32, i32]
Special-case notations:
// params only, no return (-> void omitted)
fn[i32]
// neither params nor return
fn[]
Function References
def greet():
print("Hello, World!\n");
def main():
// '::' is the reference operator
fn[() -> void] g = ::greet;
g();
Coremodule andexternfunctions cannot be referenced (::printis an error).- Callables are freed/overwritten on reassignment; copying a callable clones its frame.
Callables as Values
Pass, return, and mutate callables like any value:
def apply_op(fn[i32, i32 -> i32] op, i32 x, i32 y) -> i32:
return op(x, y);
def get_sub() -> fn[i32, i32 -> i32]:
return ::sub;
// callables pass by reference
def set_sub(mut fn[i32, i32 -> i32] op):
op = ::sub;
def main():
fn[i32, i32 -> i32] op = get_sub();
i32 res = apply_op(op, 20, 10);
set_sub(op);
res = apply_op(op, res, 5);
Persistent Locals
persistent keeps local state across calls; per callable instance, not static/shared:
def counter() -> i32:
persistent i32 c = 0;
// '++' not usable in expression contexts yet
i32 current = c;
c++;
return current;
def main():
fn[() -> i32] c1 = ::counter;
fn[() -> i32] c2 = ::counter;
c1(); // 0
c1(); // 1
c2(); // 0
- Cannot combine
persistentwithconst. - Direct calls (
counter()) reset the state each invocation; only callable instances persist.
Use cases: counters, rate-limiters (with Core.time), state machines, accumulators.
Error Sets in Callables
// possible errors in the fn type
fn[bool {ErrAssert}] f = ::may_fail;
f(true) catch err:
switch err:
ErrAssert(e): print($"ErrAssert = {e}\n");
anyerror(e): print($"anyerror = {e}\n");
An unspecified error set expands to {anyerror}:
// This expands to the type fn[bool -> void {anyerror}]
fn[bool] f = ::may_fail;
so any function reference can be stored regardless of the errors it may throw.