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 powerful 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 especially elegant for transformations. You'll see it extensively in quantum computing, where gates transform qubits:

kettle
q = qubit()
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".

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 with Accumulators ​

Kettle's for loops use accumulators instead of mutation:

kettle
-- Sum numbers 1 to 10
total = for i in range(1, 11) with sum = 0
  sum + i
end for
-- total = 55

The with clause initializes the accumulator. Each iteration produces a new value that becomes the accumulator for the next iteration.

Expression Sequencing ​

Use semicolons to sequence multiple expressions, returning the last one:

kettle
-- Sequence expressions; the last value is returned
result = (print("computing..."); 42)  -- result is 42

-- Useful in lambdas that need side effects
numbers | map(fn(x: Int) -> print(to_string(x)); x * 2)

In function bodies, expressions are automatically sequenced by newlines:

kettle
fn process(x: Int) -> Int
  print("Processing...")   -- executed first
  print("Value: ${to_string(x)}")  -- executed second
  x * 2                    -- returned
end fn

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 ​