Repository navigation
Reference structs tuples
Mirrored from docs/reference/structs-tuples.md in the repo — that is the canonical source; edits to this wiki page are overwritten when the wiki is re-synced.
Thesis context: Product types test deep copy on cross-arena move for composite values. A struct with heap-bearing fields (strings, arrays) exercises the recursive
copy_intothat keeps the arena model sound at every nesting level. Tuples test that multi-return values participate in the same return-slot optimization as single values.
Both are product types — a value made of several fields. A struct names its fields and is
declared as a type; a tuple is anonymous and is how a function returns more than one value.
Both are values, deep-copied on every bind, so two never share storage.
struct Point:
x: int
y: int
struct Rect:
lo: Point
hi: Point
fn area(r: Rect) -> int:
return (r.hi.x - r.lo.x) * (r.hi.y - r.lo.y)
fn main():
a := Point(1, 2) # positional construction, fields in declaration order
r := Rect(a, Point(4, 6))
r.lo.x = 100 # nested field write, in place
A field may be int, float, bool, string, an array (including an array of structs —
even of the struct being defined, so children: [Node] builds a recursive tree), an
Option (a nullable field, age: Option(int)), or another struct. A field that would make
the struct infinitely large by value — next: Option(Node) directly inside Node — is a
compile error; use indirection through an array ([Node]), whose elements are arena-allocated.
Structs are values, and the copy is deep: a field that owns heap bytes (a string or
array, at any nesting depth) is duplicated too, so copying a struct copies its whole tree and
two struct variables never share storage.
struct Person:
name: string
tags: [string]
a := Person("Ada", ["x"])
b := a # deep copy: b.name and b.tags are independent
b.name = "Alan" # never touches a
Fields are read with p.x and written with p.x = v, including nested (r.lo.x = v) and an
array-field element (p.tags[0] = v). Construction is positional, in declaration order, and
a struct must be declared before it is used as a type. Two structs compare by value with
==/!= — field-wise, recursing into nested structs, arrays, and strings — so a == b is
true exactly when b is an independent copy of a. A struct may be a "method" receiver; see
Functions.
A tuple (T1, ..., Tn) (2–8 elements) is an anonymous product — the way a function returns
more than one thing. return a, b builds one, and you destructure it at the call:
fn divmod(a: int, b: int) -> (int, int):
q := a / b
return q, a - q * b # builds the tuple (q, remainder)
fn main():
quot, rem := divmod(17, 5) # destructure -> quot = 3, rem = 2
Tuples are first-class values, not only a return convention: store one whole
(t := divmod(17, 5)), index it by position (t.0, t.1), write a literal (p := (10, 20)),
pass it as an argument or a struct field, and compare two with == (element-wise). Any
element type works, including heap ones ((string, [int])); a tuple is deep-copied on bind
like everything else, so two are independent. Destructuring comes in two forms — a, b := f()
declares fresh locals, a, b = f() assigns into existing variables. A tuple element is also a
writable place: t.0 = v updates it in place, and value semantics is preserved — a copy taken
beforehand is unaffected.
Design background: if you want the why — why deep-copied aggregates stay sound, and why a struct that would contain itself by value is rejected (use indirection through an array) — see the aggregates design note.
The reader docs here are mirrored from /docs in the repo — the canonical source. · tycho-lang.com · MIT licensed
- Tutorial
- The Tycho thesis: value semantics makes implicit arenas work
- Architecture & project status
- From
mallocto implicit arenas
- Tycho language reference
- Basics
- Types
- Functions and closures
- Structs and tuples
- Enums, options, and
match - Arrays and slices
- Subscripts (user-defined projections)
- Maps
- Generics
- Concurrency
- FFI (calling C)
- Packages
- Builtins
- Memory model in the self-hosted compiler
- Tycho aggregates: arrays & structs under value semantics
- Maps with arbitrary value types
m[k]as a place: in-place map-value mutation- Generics (monomorphized)
- Concurrency in Tycho
- FFI — calling C from Tycho
- Packages & modules
- corelib — Tycho's standard library
- Performance: the self-hosted transpiler vs the C one
- Debugging generated C