Skip to content

Console

Write to standard output with println, and understand the effect it carries.

Updated View as Markdown

println writes a line to the host runtime’s standard output. It is the output function used throughout this book.

fn main(): void {
    println("hello")
}

It takes exactly one string, so values are formatted before the call — most often with interpolation:

fn main(): void {
    name := "ada"
    count := 3
    println("${name} has ${count} items")
}

Concatenation works too, but every operand must already be a string:

fn main(): void {
    n := 42
    println("n = " + n.to_string())
}

Interpolation uses Display

"${value}" calls the value’s to_string through the Display trait, so implementing Display makes a user type printable:

struct Point { x: int, y: int }

impl Display for Point {
    fn to_string(self): string => "(${self.x}, ${self.y})"
}

fn main(): void {
    println("${Point { x: 1, y: 2 }}")
}

A nested " inside an interpolation hole is not supported — bind the string to a local first rather than escaping it.

println is a suspending call

This is the surprising part, and it explains diagnostics you will meet early. println is declared @host("atoll_runtime::io", "println") @suspend, so any function that calls it acquires the Suspend effect, and so does every caller above it.

The annotation is about which ABI the call lowers to, not about latency: the host handler completes inline and never waits on the event loop, but it hands the continuation back through the suspending ABI. (Omitting it was historically a silent miscompile — a caller lowered as non-suspending around a suspending call lost its return value.)

You do not write that effect down. Effects are inferred, and ordinary Atoll code simply calls println:

fn report(total: int): void {
    println("total=${total}")
}

fn main(): void {
    report(7)
}

That program compiles and runs. It also emits a warning, and this is the part worth internalising early:

warning[ATOLL2032]: fn `report` inherits effect `suspend` from a
transitively-called callee but its declared `using [..]` row does not list
`suspend`

ATOLL2032 is noise here — leave it. The diagnostic suggests declaring an effect row, but effect rows are an explicit-contract feature that real Atoll code essentially never writes; there is not one in the compiler’s own sample projects or prelude. Nothing about the program is wrong, and the warning does not stop compilation. See Effects for when a row is genuinely worth writing.

Keep println out of a function you want to stay non-suspending — a pure computation should return its value and let the caller print it:

fn double(x: int): int {
    return x * 2
}

fn main(): void {
    println("${double(21)}")
}

Capability and redirection

println routes through the host boundary rather than writing directly, which has two consequences:

  • A sandboxed deployment can deny the atoll_runtime::io capability, and then println calls fail at load rather than silently doing nothing.
  • An embedder can divert output into a buffer instead of the process’s stdout, which is how the runtime’s tests capture program output.

There is no print without a newline, no formatted-print variant, and no prelude logger. Build the complete line as a string and pass it.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close