Skip to main content
Functions in Kairo are explicit by design. Every callable has a visible signature — parameter names, types, and return type — and there are no hidden overloads, no implicit receivers, and no magic static contexts. Kairo distinguishes between three kinds of callable: free functions that live at module level, instance methods that operate on a specific object or value, and type functions that belong to the type itself rather than to any instance. Understanding which kind to reach for is a core part of writing idiomatic Kairo.

Free Functions

A free function is declared at module level using the func keyword. It is not attached to any type. Free functions are the right choice for pure logic, utility operations, and module entry points.
Apply public to make a free function accessible to other modules. Without a visibility modifier, the function is internal — visible only within the declaring module.

Instance Methods

Declare a function inside a value or object block to make it an instance method. Inside an instance method, use this to refer to the current instance.
Instance methods on a value type cannot mutate state — all members of a value are immutable, so this is read-only.
this is a contextual keyword. It is only meaningful inside an instance method or init block. You cannot use this in a free function or a type func.

Type Functions

A type function belongs to the type itself, not to any instance. Use type func in place of the static keyword you may know from other languages. Type functions have no access to this. Type functions are the canonical way to provide named constructors, factory methods, and type-level utilities.
Call a type function using the type name as the qualifier:
Use type func for any logic that produces or validates an instance before construction — such as parsing, validation, or ID generation. This keeps init focused purely on field assignment.

Object Initializers (init)

Every object has exactly one init block in v0.1. The init receives the initial values for the object’s fields and assigns them using this.
Construct an object by calling init with named arguments:
init always uses named arguments at the call site. Positional argument order is not guaranteed to be stable for init, so named arguments are required. See the Parameters section below for how this differs from regular function calls.

Parameters

Positional and Named Arguments

Regular function calls support either positional arguments or named arguments — but not a mix of both in a single call.
You cannot mix positional and named arguments in the same call in v0.1. Choose one style for the entire argument list.

Parameter Types

Every parameter must have an explicit type annotation in the function signature. There is no parameter inference.

Return Types and the return Statement

Specify the return type after the parameter list, separated by a colon. Use return to exit the function and produce a value. A function with no return type annotation returns nothing (equivalent to Void).
return can appear anywhere in a function body. Execution of the current function stops immediately at the return statement.

Async Functions

Mark a function async to indicate that it may suspend while waiting for I/O, a network call, or another asynchronous operation. Inside an async function, use await to explicitly suspend at each asynchronous call site.
await is only valid inside an async function. There is no hidden async promotion — if you call an async function, you must either await it inside another async function or explicitly handle the asynchronous context.
Keep async functions focused on a single I/O concern. Compose them by await-ing other async functions rather than mixing business logic and I/O in the same function.

Summary

Free function

Module-level func. No receiver, no this. Use for pure logic and module entry points.

Instance method

func inside a value or object. Has access to this. Use for behaviour that belongs to a specific instance.

Type function

type func inside a type. No this. Use for factories, named constructors, and type-level utilities.

Async function

async func at any level. Use await to suspend explicitly. Use for I/O, network calls, and any deferred work.