Basic Syntax

Basic Syntax

This page covers the core syntax and fundamental language constructs in Kairo.

Variables

Variables are immutable by default. Use let mut for mutable variables.

let x = 42;           // immutable — cannot be reassigned
let mut y = 10;       // mutable
let z: i32 = 100;     // explicit type annotation

y = 20;               // ok — y is mutable
// x = 5;            // error — x is immutable

Functions

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

// Functions with no return value
fn greet(name: str) {
    print(f"Hello, {name}!");
}

// Error-returning functions (T! means "T or error")
fn divide(a: f64, b: f64) -> f64! {
    if b == 0.0 {
        return error("Division by zero");
    }
    return a / b;
}

Calling error-returning functions

Use ! to propagate errors (like Rust’s ?), or handle them explicitly:

fn main() {
    // Propagate error up
    let result = divide(10.0, 2.0)!;

    // Or handle it
    match divide(10.0, 0.0) {
        ok(v)  => print(f"Result: {v}"),
        err(e) => print(f"Error: {e}"),
    }
}

Control Flow

if / else

if x > 0 {
    print("positive");
} else if x < 0 {
    print("negative");
} else {
    print("zero");
}

for loops

// Range loop
for i in 0..10 {
    print(f"i = {i}");
}

// Inclusive range
for i in 0..=10 {
    print(f"i = {i}");
}

// Iterate over array
let arr = [1, 2, 3, 4, 5];
for x in arr {
    print(f"{x}");
}

while

let mut n = 10;
while n > 0 {
    print(f"n = {n}");
    n -= 1;
}

match

match value {
    0        => print("zero"),
    1..=9    => print("single digit"),
    10..=99  => print("two digits"),
    _        => print("large"),
}

Types

Primitive types

let a: i8   = 127;
let b: i16  = 32767;
let c: i32  = 2147483647;
let d: i64  = 9223372036854775807;
let e: u8   = 255;
let f: u32  = 4294967295;
let g: f32  = 3.14;
let h: f64  = 3.14159265358979;
let i: bool = true;
let j: char = 'K';

Arrays

let arr: [i32; 5] = [1, 2, 3, 4, 5];
let first = arr[0];
let len = arr.len();  // 5

Strings

let s: str = "Hello, Kairo!";
let len = s.len();
let upper = s.to_upper();

// f-strings for interpolation
let name = "world";
let msg = f"Hello, {name}!";

Structs

struct Point {
    x: f64,
    y: f64,
}

impl Point {
    fn new(x: f64, y: f64) -> Point {
        return Point { x, y };
    }

    fn distance(self, other: Point) -> f64 {
        let dx = self.x - other.x;
        let dy = self.y - other.y;
        return (dx*dx + dy*dy).sqrt();
    }
}

fn main() {
    let p1 = Point::new(0.0, 0.0);
    let p2 = Point::new(3.0, 4.0);
    print(f"Distance: {p1.distance(p2)}");  // 5.0
}

Interfaces

Kairo uses interfaces (similar to traits/protocols) for polymorphism:

interface Printable {
    fn print(self);
}

struct Cat {
    name: str,
}

impl Printable for Cat {
    fn print(self) {
        print(f"Cat: {self.name}");
    }
}

Generics

fn max<T: Comparable>(a: T, b: T) -> T {
    if a > b { return a; }
    return b;
}

let bigger = max(10, 20);       // i32
let bigger2 = max(3.14, 2.71);  // f64