POLYTONE — the AI-native programming language

Guide

Tuples & destructuring

A tuple groups a fixed number of values of different types. Since Sprint 102 you take one apart the same way you match anything else — by pattern, with named binders.

roster.pt
import lists

fn main() -> Void:
    let names = ["ada", "grace", "alan"]
    let scores = [91, 84, 78]
    for (rank, (name, score)) in lists.enumerate(lists.zip(names, scores)):
        print("{rank}: {name} = {score}")

    let (lo, hi) = (3, 9)
    print("range {lo}..{hi}")

Decomposition is by pattern only — let (a, b) = pair, case (a, b): in a match, and the for (k, v) in … loop binder — and the patterns nest, so for (rank, (name, score)) in … peels a tuple out of a tuple. There is no positional .0/.1 accessor: a name at every position is the LLM-first choice. A let or for binder must be irrefutable (only bindings and _), so a literal there is a compile error that points you to a match.

Map.entries() -> List[Tuple[K, V]] is the idiomatic way to walk a map's pairs (for x in map: still iterates keys). The collection helpers that produce pairs — lists.zip, enumerate, unzip, group_by, and maps' entry-wise combinators — all read cleanly now that a pair can be taken apart.