Data Types
Kōdo lets you define custom data types using struct and enum. Pattern matching with match provides a safe way to destructure values and handle every case.
Structs
Section titled “Structs”A struct groups related values under named fields:
struct Point { x: Int, y: Int}Creating Structs
Section titled “Creating Structs”Create a struct value by providing all fields:
let origin: Point = Point { x: 0, y: 0 }let p: Point = Point { x: 3, y: 4 }Accessing Fields
Section titled “Accessing Fields”Use dot notation to access individual fields:
fn get_x(p: Point) -> Int { return p.x}
fn main() { let p: Point = Point { x: 10, y: 20 } print_int(p.x) print_int(p.y)}Structs as Function Parameters
Section titled “Structs as Function Parameters”Structs can be passed to and returned from functions:
struct Point { x: Int, y: Int}
fn translate(p: Point, dx: Int, dy: Int) -> Point { return Point { x: p.x + dx, y: p.y + dy }}
fn main() { let p: Point = Point { x: 1, y: 2 } let q: Point = translate(p, 10, 20) print_int(q.x) print_int(q.y)}Output:
1122Internally, structs are passed by pointer — there is no copy overhead for large structs.
An enum defines a type that can be one of several named variants. Each variant can optionally carry data:
enum Color { Red, Green, Blue}
enum Shape { Circle(Int), Rectangle(Int, Int)}Color has three variants with no data. Shape has two variants: Circle carries a radius (Int) and Rectangle carries width and height (Int, Int).
Creating Enum Values
Section titled “Creating Enum Values”Use the EnumName::Variant(args) syntax:
let s: Shape = Shape::Circle(5)let r: Shape = Shape::Rectangle(10, 20)Pattern Matching with match
Section titled “Pattern Matching with match”match is the primary way to work with enums. It destructures the value and binds contained data to variables:
fn area(s: Shape) -> Int { match s { Shape::Circle(r) => { return r * r * 3 } Shape::Rectangle(w, h) => { return w * h } }}Each arm of a match specifies a pattern (Shape::Circle(r)) and a body to execute when the value matches that pattern. The contained values are bound to the names you choose (r, w, h).
Match is Exhaustive
Section titled “Match is Exhaustive”Every match must cover all variants. If you forget one, the compiler will tell you. This prevents a common category of bugs where a new variant is added but not handled everywhere.
Enums as Function Parameters
Section titled “Enums as Function Parameters”Like structs, enums can be passed to and returned from functions:
enum Direction { Up, Down, Left, Right}
fn move_point(p: Point, dir: Direction, amount: Int) -> Point { match dir { Direction::Up => { return Point { x: p.x, y: p.y + amount } } Direction::Down => { return Point { x: p.x, y: p.y - amount } } Direction::Left => { return Point { x: p.x - amount, y: p.y } } Direction::Right => { return Point { x: p.x + amount, y: p.y } } }}Complete Example
Section titled “Complete Example”Here’s a program that combines structs, enums, and pattern matching:
module geometry { meta { purpose: "Calculate areas of shapes" version: "0.1.0" }
struct Point { x: Int, y: Int }
enum Shape { Circle(Int), Square(Int), Rectangle(Int, Int) }
fn area(s: Shape) -> Int { match s { Shape::Circle(r) => { return r * r * 3 } Shape::Square(side) => { return side * side } Shape::Rectangle(w, h) => { return w * h } } }
fn main() { let c: Shape = Shape::Circle(5) let sq: Shape = Shape::Square(4) let r: Shape = Shape::Rectangle(3, 7)
print_int(area(c)) print_int(area(sq)) print_int(area(r)) }}Output:
751621Float64
Section titled “Float64”Kōdo supports 64-bit floating-point numbers with full arithmetic:
let pi: Float64 = 3.14159let radius: Float64 = 5.0let area: Float64 = pi * radius * radius
println_float(area)All arithmetic (+, -, *, /, %), comparison (==, !=, <, >, <=, >=), and negation (-x) operators work with Float64 values.
String Operators
Section titled “String Operators”Strings support concatenation with the + operator:
let greeting: String = "Hello, " + "world!"println(greeting)
let name: String = "Kōdo"let msg: String = "Welcome to " + nameprintln(msg)Strings also support equality comparison with == and !=, which compares by content (not by pointer):
let a: String = "hello"let b: String = "hello"if a == b { println("strings are equal")}See Modules and Imports for the full list of string methods (length, contains, split, trim, concat, index_of, replace, etc.).
Next Steps
Section titled “Next Steps”- Closures — closures, lambda lifting, and higher-order functions
- Generics — parameterize your types with type variables
- Error Handling — use
Option<T>andResult<T, E>for safe error handling - Contracts — add runtime verification to your functions