Walrus/Language

Functions

Top-level functions, nested functions, typed signatures, closures, capture rules, and task functions in Walrus.

Updated April 13, 20264 min readWalrus / Functions

Functions are central to Walrus. They are named, typed, and can be nested to create closures. Walrus also supports task functions through @task, which marks work that should be started with spawn and resolved with await.

Top-level functions

Walrus
fn abs(x: int) -> int:
    if x < 0:
        return 0 - x
    return x

Parameters and return types are written explicitly.

Nested functions

You can declare a function inside another function:

Walrus
fn makeAdder(k: int) -> fn(int) -> int:
    fn add(x: int) -> int:
        return x + k
    return add

That nested function becomes a closure value when it captures names from the outer scope.

Immutable captures

Most closure examples start with immutable capture:

Walrus
fn makeAdder(k: int) -> fn(int) -> int:
    fn add(x: int) -> int:
        return x + k
    return add

Here, k is captured and read by the returned function.

Mutable captures

Use var when the nested function must mutate a captured local:

Walrus
fn counter() -> fn() -> int:
    var i = 0

    fn next() -> int:
        i += 1
        return i

    return next

This is also where ownership rules matter. Copy values are captured cheaply. Owned values move into escaping closures. Borrowed values only work when the closure stays local.

Function types

Walrus exposes function types directly in annotations:

Walrus
fn makeAdder(k: int) -> fn(int) -> int
fn counter() -> fn() -> int

Task Functions

Use @task when a function is meant to participate in Walrus' thread-aware task model:

Walrus
@task
fn buildStuff() -> int:
    return 5

Task functions are still ordinary typed functions in source code, but semantically they mean:

  • this function is schedulable work
  • it should be started with spawn
  • its result is consumed through a task handle and await

Starting a task

Walrus
let task = spawn buildStuff()
let result = await task

Normal calls are rejected

This is intentionally invalid:

Walrus
@task
fn buildStuff() -> int:
    return 5

fn main() -> int:
    return buildStuff()

Walrus reports:

TEXT
task functions must be started with spawn

Threaded intent

Task functions are part of the language's move toward threaded execution. In the current first pass, they still run through a synchronous runtime path internally, but the language shape is already correct for future worker-thread scheduling.