Skip to main content

Language overview

This page stays intentionally high level. It focuses on syntax and patterns that are already used in the Kaede repository and examples.

Imports and names

Kaede uses import for modules and use to bring names into shorter scope.

import std.net.http
import std.sync

use std.net.http.Status
use std.sync.Mutex

Qualified names use :::

mut app := std.net.http.App::new()

Module layout

A module can be a single file or a file plus a sibling directory of submodules.

  • net.kd defines module net.
  • net/tcp.kd defines module net.tcp.
  • The two coexist: net.kd holds the body of net, and net/*.kd add submodules under the same net.* namespace.
  • A directory without a sibling same-name file has no module body; only its submodules are importable. import net.tcp works, but import net errors.
  • If an item in the body shares a name with a sibling submodule (e.g. net.kd exports fun tcp() and net/tcp.kd also exists), the body item takes precedence in expression position. Avoid the clash.
src/
├── net.kd # module: net (optional body)
├── net/
│ ├── tcp.kd # module: net.tcp
│ └── http.kd # module: net.http
└── main.kd

Bindings

Kaede supports both the short declaration form and let bindings:

vec := Vector<i32>::new()
mut app := std.net.http.App::new()
let count: i32 = 3
const page_size: u64 = 4096

In practice, current Kaede code tends to use:

  • := for local bindings when the type is obvious from the right-hand side
  • mut ... := for mutable locals with inferred types
  • let when you want the explicit let form, especially with a type annotation such as let count: i32 = 3
  • const for typed local compile-time constants

let x = 1 and let mut x = 1 are also valid. const currently requires a type annotation and a compile-time constant initializer.

Functions and return types

Functions declare return types with -> Type.

fun greet() {
println("hello, world!")
}

fun add(a: i32, b: i32) -> i32 {
return a + b
}

Closures

Closures are commonly used in HTTP handlers and collection helpers.

app.get("/", |req, res| {
res.send("Kaede!")
})

subscribers.retain(|subscriber| {
if subscriber.events.try_send(json) {
return true
}

subscriber.events.close()
return false
})

Data types and methods

Structs, enums, and impl blocks are part of everyday Kaede code.

struct Counter {
value: u64,
}

impl Counter {
fun new(start: u64) -> mut Counter {
return Counter { value: start }
}

fun next(mut self) -> u64 {
id := self.value
self.value = id + 1
return id
}
}

Continue with: