Skip to content

Language Basics ​

This chapter covers the fundamental building blocks of Kettle programs.

Variables ​

Variables are declared with = and are immutable by default:

kettle
name = "Alice"
age = 30
pi = 3.14159

Kettle uses type inference, so you rarely need to write type annotations. The compiler figures out that name is a String, age is an Int, and pi is a Float.

Rebinding with <- ​

To update a variable, use the rebind operator <-:

kettle
count = 0
count <- count + 1
count <- count + 1
print(to_string(count))  -- prints "2"

This isn't mutation in the traditional senseβ€”it creates a new binding that shadows the previous one.

Rebind with Function Application ​

A common pattern is rebinding a variable through a function:

kettle
fn double(n: Int) -> Int
  n * 2
end fn

x = 5
x <- double(x)    -- x is now 10
x <- double(x)    -- x is now 20

When the variable being rebound is the argument to a function, Kettle provides syntactic sugarβ€”you can omit the argument:

kettle
x = 5
x <- double       -- equivalent to: x <- double(x)

This "apply and rebind" pattern is used throughout Kettle. You'll see it with gates, where gates transform qubits:

kettle
q: Qubit = 0
q <- hadamard     -- equivalent to: q <- hadamard(q)
q <- pauli_x      -- equivalent to: q <- pauli_x(q)

The same <- operator works for both classical and quantum codeβ€”it's Kettle's unified way of expressing "transform this value".

Unified Syntax

Kettle uses the same constructs everywhere:

ClassicalWith qubitsPattern
x = 5q: Qubit = 0Binding
x <- doubleq <- hadamardRebind
compute(x)measure(q)Function call

There's no separate "quantum syntax" β€” qubits are types, gates are functions, quantum is an effect.

Compound Assignment ​

Kettle also supports compound assignment operators for common updates:

kettle
x = 10
x += 5    -- x is now 15 (same as x <- x + 5)
x -= 3    -- x is now 12
x *= 2    -- x is now 24

Available compound operators:

  • +=, -= β€” addition, subtraction
  • *=, /= β€” multiplication, division (for Float)
  • ^= β€” XOR (for Int)

These are particularly useful in loops and are required for reversible computations.

Basic Types ​

Kettle has several built-in types:

TypeDescriptionExamples
IntInteger numbers42, -17, 0
FloatFloating-point numbers3.14, -0.5, 1.0
StringText"hello", "Kettle"
BoolBoolean valuesTrue, False
UnitNo meaningful value(used for side-effect functions)

String Interpolation ​

Use ${} to embed expressions in strings:

kettle
name = "Bob"
age = 25
print("${name} is ${to_string(age)} years old")

Functions ​

Functions are defined with fn and end fn:

kettle
fn greet(name: String) -> String
  "Hello, ${name}!"
end fn

fn add(a: Int, b: Int) -> Int
  a + b
end fn

The last expression in a function is its return valueβ€”no return keyword needed.

Calling Functions ​

kettle
message = greet("Alice")
sum = add(2, 3)

Functions Without Parameters ​

kettle
fn get_answer() -> Int
  42
end fn

Functions Returning Unit ​

Functions that perform side effects typically return Unit. Functions that print require the IO effect:

kettle
fn say_hello() -> Unit with IO
  print("Hello!")
end fn

Control Flow ​

Match Expressions ​

Pattern matching with match:

kettle
fn describe(n: Int) -> String
  match n
    0 -> "zero"
    1 -> "one"
    _ -> "many"
  end match
end fn

The _ pattern matches anything (wildcard).

Boolean Matching ​

A common pattern for conditional logic:

kettle
fn abs(n: Int) -> Int
  match n >= 0
    True -> n
    False -> -n
  end match
end fn

Loops ​

For Loops ​

Iterate over lists or ranges:

kettle
-- Simple iteration (no accumulator)
for item in ["apple", "banana", "cherry"]
  print(item)
end for

-- Iterate over a range
for i in range(1, 4)
  print(to_string(i))  -- prints 1, 2, 3
end for

For Loops with Accumulators ​

Use with to carry state across iterations:

kettle
-- Single accumulator: sum numbers
total = for i in range(1, 11) with sum = 0
  sum + i
end for
-- total = 55

-- Multiple accumulators: Fibonacci
(a, _) = for _ in range(0, 10) with a = 0, b = 1
  (b, a + b)
end for
-- a = 55

Each iteration produces a new value that becomes the accumulator for the next iteration.

While Loops ​

Loop while a condition is true:

kettle
-- Count down
result = while n > 0 with n = 5
  n - 1
end while
-- result = 0

-- GCD with multiple accumulators
(result, _) = while b > 0 with a = 48, b = 18
  (b, a % b)
end while
-- result = 6

Comments ​

Single-line comments start with --:

kettle
-- This is a comment
x = 42  -- inline comment

Note: Kettle only has single-line comments. For longer explanations, use multiple -- lines.

Operators ​

Arithmetic ​

  • +, -, *, / β€” basic math
  • % β€” modulo (remainder)

Comparison ​

  • ==, != β€” equality
  • <, >, <=, >= β€” ordering

Logical ​

  • && β€” and
  • || β€” or
  • ! β€” not (prefix)

Example ​

kettle
fn is_valid_age(age: Int) -> Bool
  age >= 0 && age <= 150
end fn

fn main() -> Unit using file_io
  ages = [25, -5, 200, 42]
  for age in ages
    valid = is_valid_age(age)
    print("${to_string(age)}: ${to_string(valid)}")
  end for
end fn

Next Steps ​