Data Types ​
Kettle has a rich set of data types for structuring your programs.
Records ​
Records are named collections of fields:
kettle
type Point = record
x: Float
y: Float
end record
type Person = record
name: String
age: Int
end recordCreating Records ​
kettle
origin = Point { x: 0.0, y: 0.0 }
alice = Person { name: "Alice", age: 30 }Accessing Fields ​
Use dot notation:
kettle
print(alice.name) -- "Alice"
print(to_string(origin.x)) -- "0.0"Updating Records ​
Create a new record with some fields changed:
kettle
moved = Point { x: origin.x + 1.0, y: origin.y }Variants ​
Variants (also called sum types or tagged unions) represent values that can be one of several forms:
kettle
type Shape = variant
Circle(radius: Float)
Rectangle(width: Float, height: Float)
Triangle(base: Float, height: Float)
end variantCreating Variants ​
kettle
c = Circle(5.0)
r = Rectangle(10.0, 20.0)Pattern Matching ​
Use match to handle each case:
kettle
fn area(shape: Shape) -> Float
match shape
Circle(r) -> 3.14159 * r * r
Rectangle(w, h) -> w * h
Triangle(b, h) -> 0.5 * b * h
end match
end fnUnit Variants ​
Variants can have no data:
kettle
type Direction = variant
North
South
East
West
end variant
fn opposite(d: Direction) -> Direction
match d
North -> South
South -> North
East -> West
West -> East
end match
end fnOption and Result ​
Option Type ​
Option[T] represents a value that might be absent:
kettle
type Option[T] = variant
Some(value: T)
None
end variantUse it instead of null:
kettle
fn find_index(lst: List[Int], target: Int) -> Option[Int]
for (item, idx) in enumerate(lst) with result = None
match item == target
True -> Some(idx)
False -> result
end match
end for
end fn
fn main() -> Unit using file_io
numbers = [10, 20, 30, 40]
match find_index(numbers, 30)
Some(i) -> print("Found at index ${to_string(i)}")
None -> print("Not found")
end match
end fnResult Type ​
Result[T, E] represents success or failure:
kettle
type Result[T, E] = variant
Ok(value: T)
Err(error: E)
end variantUse it for operations that can fail:
kettle
fn parse_positive(s: String) -> Result[Int, String]
match to_int(s)
Some(n) ->
match n > 0
True -> Ok(n)
False -> Err("Must be positive")
end match
None -> Err("Invalid number: ${s}")
end match
end fnTuples ​
Tuples group values of different types:
kettle
pair = (1, "hello")
triple = (True, 3.14, "test")
-- Destructuring
(flag, value, label) = tripleLists ​
Lists hold multiple values of the same type:
kettle
numbers = [1, 2, 3, 4, 5]
names = ["Alice", "Bob", "Carol"]
empty: List[Int] = []Accessing Elements ​
Use get_at to access elements by index (returns Option since index might be out of bounds):
kettle
numbers = [10, 20, 30, 40]
-- get_at(index, list) - pipe-friendly
first = numbers | get_at(0) -- Some(10)
third = numbers | get_at(2) -- Some(30)
oob = numbers | get_at(99) -- None (out of bounds)
-- Handle the Option
match numbers | get_at(0)
Some(n) -> print("First: ${to_string(n)}")
None -> print("List is empty")
end matchFor convenience, use head and last:
kettle
first = head(numbers) -- Some(10)
final = last(numbers) -- Some(40)Common Operations ​
kettle
-- Length
len = length(numbers)
-- Append (pipe-friendly)
more = numbers | append(6)
-- Concatenate
all = numbers | concat([6, 7, 8])
-- Transform
doubled = numbers | map(fn(x: Int) -> x * 2)
-- Filter
evens = numbers | filter(fn(x: Int) -> x % 2 == 0)
-- Reduce
total = numbers | fold(0, fn(acc: Int, x: Int) -> acc + x)Type Annotations ​
While Kettle infers most types, you can add annotations:
kettle
-- Variable annotation
count: Int = 0
-- Function with full annotations
fn add(a: Int, b: Int) -> Int
a + b
end fn
-- Empty collections need annotations
empty_list: List[String] = []Next Steps ​
- Generics — Parameterized types
- Functional Programming — Working with data using pipes and HOFs