Values, Variables, and Basic Types
This chapter covers numbers, strings, and mutable state. Each example runs as a single file: save it and execute tauto run filename.
3.1 Give values names
let names a value. var creates a cell whose contents can be changed. Assignment uses :=; new bindings also use let x := value and var x := value.
let a := 10
let b: i64 := 32
perform show("sum", a + b)
var count: i64 := 0
count := count + 1
perform show("count", count)
// A mutable binding can change, while a let binding cannot be reassigned.
sum = 42 count = 1
sum = 42
count = 1
A let binding cannot be reassigned; a var binding can. Ownership rules apply to both (Chapter 7).
3.2 Types determine what numbers mean
Numeric types have explicit meanings.
| Type | Meaning | Key point |
|---|---|---|
i32, i64 | Fixed-width signed integers | Arithmetic overflow is a runtime error |
u8, u32, u64 | Fixed-width unsigned integers | Arithmetic does not implicitly convert widths |
Decimal | Exact decimal numbers | Useful for decimal calculations such as money |
Float | Floating-point numbers | Account for approximation error |
Bool | true / false | Used in conditions |
Text | Strings | Shared data that can be duplicated |
() | The unit type | Computations with no meaningful result |
Never | A type with no values | Used for computations that do not return |
Tauto does not automatically mix i64 and i32 in addition. Trying it produces a type error.
let a: i32 := 1
let b: i64 := 2
perform show("x", a + b)
// This deliberately mixes integer widths and must be rejected.
✗ program error 3:19: `+` of i32 and i64: the operands differ
ch03-mix-error.taut:3:19: type error: `+` of i32 and i64: the operands differ
To change widths, use explicit conversions such as I64::of_i32 or I32::of_i64. A value outside the destination's range is not silently rounded; it causes a runtime error (the number is too large).
let a: i32 := 1
let b: i64 := 2
perform show("sum", I64::of_i32(a) + b)
perform show("back", I32::of_i64(b))
// Convert the integer width explicitly before adding.
sum = 3 back = 2
sum = 3
back = 2
3.3 Arithmetic and comparisons
Integer division does not use /. Use the dedicated functions div(a, b) and mod(a, b).
let a := 7
let b := 3
let product := a * b
let quotient := div(a, b)
let remainder := mod(a, b)
let same := a == b
perform show("p", product)
perform show("q", quotient)
perform show("r", remainder)
perform show("same", same)
// Observe multiplication, division, remainder, and comparison separately.
p = 21 q = 2 r = 1 same = false
p = 21
q = 2
r = 1
same = false
Writing 7 / 2 produces an error explaining the available forms:
type error: integer `/` is a type error: write div(a, b), mod(a, b), or decimal(a) / decimal(b)
Division by zero is a runtime error. It is not necessarily ruled out before execution.
3.4 Strings
Strings have type Text. Double-quoted literals ("...") process escapes, while single-quoted literals ('...') do not.
import std::prelude::Shared
let greeting := "Hello, Tauto!"
let path := 'C:\Users\example\Documents'
let joined := concat(greeting, " Good day")
perform show("text", joined)
perform show("path", path)
// Concatenate text explicitly and preserve backslashes in the raw path.
text = "Hello, Tauto! Good day" path = "C:\\Users\\example\\Documents"
text = "Hello, Tauto! Good day"
path = "C:\\Users\\example\\Documents"
show formats values for display, so the path's backslashes appear doubled in the output. The value itself is C:\Users\example\Documents.
To concatenate Text, use concat, not +. The expression "x" + "y" is a type error: +` of Text: not a number. Numeric and string operations are designed to have an unambiguous meaning.
Exercise 3.1: Bind two integers with let and observe their sum, difference, and product with show.