> ## Documentation Index
> Fetch the complete documentation index at: https://docs.astrakairo.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Kairo Functions: Free Functions, Methods, and Async

> Define free functions, instance methods, type functions, and async callables in Kairo with explicit signatures and predictable calling conventions.

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.

```kairo theme={null}
module Demo.Greetings

public func greet(name: Text): Text {
    return "Hello, " + name + "!"
}

public func main() {
    let message = greet("Kairo")
    Pulse.Console.out.writeLine(message)
}
```

Apply `public` to make a free function accessible to other modules. Without a visibility modifier, the function is `internal` — visible only within the declaring package.

## 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.

```kairo theme={null}
public object Counter {
    var count: Int32

    init(start: Int32) {
        this.count = start
    }

    func increment() {
        this.count = this.count + 1
    }

    func value(): Int32 {
        return this.count
    }
}
```

Instance methods on a `value` type cannot mutate state — all members of a `value` are immutable, so `this` is read-only.

```kairo theme={null}
public value Money {
    amount: Decimal
    currency: Text

    func formatted(): Text {
        return this.amount.toString() + " " + this.currency
    }
}
```

<Note>
  `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`.
</Note>

## 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.

```kairo theme={null}
public object Customer {
    id: CustomerId
    var name: Text

    init(id: CustomerId, name: Text) {
        this.id = id
        this.name = name
    }

    type func create(name: Text): Customer {
        let id = CustomerId { value: IdGenerator.next() }
        return Customer(id: id, name: name)
    }
}
```

Call a type function using the type name as the qualifier:

```kairo theme={null}
let customer = Customer.create(name: "Astra")
```

<Tip>
  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.
</Tip>

## 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`.

```kairo theme={null}
public object Order {
    id: OrderId
    var status: OrderStatus
    var total: Money

    init(id: OrderId, total: Money) {
        this.id = id
        this.status = OrderStatus.Pending
        this.total = total
    }
}
```

Construct an object by calling its type name with named arguments matching the `init` parameters:

```kairo theme={null}
let order = Order(id: orderId, total: price)
```

<Note>
  Object construction always uses named arguments at the call site. This is a language requirement — positional argument order is not supported for `init` calls. See the [Parameters](#parameters) section below for how this differs from regular function calls.
</Note>

## 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.

```kairo theme={null}
// Positional
let result = greet("Kairo")

// Named
let result = greet(name: "Kairo")
```

<Warning>
  You cannot mix positional and named arguments in the same call in v0.1. Choose one style for the entire argument list.
</Warning>

### Parameter Types

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

```kairo theme={null}
public func transfer(from: AccountId, to: AccountId, amount: Money): Result<Transfer, TransferError> {
    // ...
}
```

## 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`).

```kairo theme={null}
public func add(a: Int32, b: Int32): Int32 {
    return a + b
}

public func logEvent(event: Text) {
    Pulse.Console.out.writeLine(event)
    // no return needed for void functions
}
```

`return` can appear anywhere in a function body. Execution of the current function stops immediately at the `return` statement.

```kairo theme={null}
public func findLabel(status: OrderStatus): Text {
    if status == OrderStatus.Delivered {
        return "Done"
    }
    return "In Progress"
}
```

## 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.

```kairo theme={null}
public async func fetchCustomer(id: CustomerId): Result<Customer, FetchError> {
    let response = await CustomerApi.get(id: id)

    match response.isSuccess {
        true {
            return Result.success(response.value)
        }
        false {
            return Result.failure(FetchError.NotFound)
        }
    }
}
```

`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.

```kairo theme={null}
public async func run() {
    let outcome = await fetchCustomer(id: targetId)

    match outcome.isSuccess {
        true  { Pulse.Console.out.writeLine("Found: " + outcome.value.name) }
        false { Pulse.Console.out.writeLine("Not found") }
    }
}
```

<Tip>
  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.
</Tip>

## Summary

<CardGroup cols={2}>
  <Card title="Free function" icon="function">
    Module-level `func`. No receiver, no `this`. Use for pure logic and module entry points.
  </Card>

  <Card title="Instance method" icon="cube">
    `func` inside a `value` or `object`. Has access to `this`. Use for behaviour that belongs to a specific instance.
  </Card>

  <Card title="Type function" icon="layer-group">
    `type func` inside a type. No `this`. Use for factories, named constructors, and type-level utilities.
  </Card>

  <Card title="Async function" icon="clock">
    `async func` at any level. Use `await` to suspend explicitly. Use for I/O, network calls, and any deferred work.
  </Card>
</CardGroup>
