TYCHO Search

Search documentation

    ↑ ↓ to move · Enter to open · Esc to close

    Subscripts (user-defined projections)

    Memory: a subscript projects into a value you already have. Nothing is stored and nothing outlives its scope.

    A subscript names a reusable read/write view into part of a value. It does not *return* a value — it yields a place, something you can read or assign through (a variable, a field, an index):

    struct Node:
        weight: int
    struct Graph:
        nodes: [Node]
    
    fn bump(n: inout int):
        n = n + 1
    
    subscript edge(g: Graph, i: int) -> inout Node:
        yield &g.nodes[i]
    
    fn main():
        g := Graph([Node(1), Node(2)])
        g.edge(1).weight = 10        # write in place through the projection — no copy
        _w := g.edge(0).weight        # read through it
        bump(&g.edge(0).weight)      # a field of the projection as an `inout` argument
    

    g.edge(i) is not a function call. At compile time it is replaced by the yielded place with the arguments substituted (g.nodes[i]), and the surrounding read or write uses that place directly. There is no runtime object — a subscript behaves exactly like the built-in &m[k].

    Array-typed projections have one restriction that struct-typed ones do not: push through the projection and element index-assign through it are refused (push's first argument must be an array variable or field; can only index-assign an array or map variable or field). Only the built-in array and map places grow in place or assign by index. To grow through a projection, pass &g.items(i) as an inout argument to a helper that pushes; to replace a whole projected value, assign the place directly (g.item(i) = v), which deep-copies into the owner's arena.

    Form

    subscript <name>(<recv>: T, <params>...) -> inout U:
        yield &<place>
    

    Rules (checked at compile time)

    What it is not

    Subscripts do not let you store a graph by reference. They make *traversing* an index-pool structure ergonomic (g.edge(i).w = … instead of g.nodes[i].w = …, and reusable accessors over composite storage); they are convenience over the index-pool idiom, not a new storage shape.


    How this is implemented — compile-time substitution and why each rule exists — is in design-subscripts, for maintainers.