Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Relationships Continued: Destructuring and Self-Referencing Methods

Destructuring bindings

A parenthesized binding target destructures a tuple result into output cells. The result must have matching arity and element types:

sheet rect_demo {
    source width: f64 = 10.0;
    source height: f64 = 4.0;
    cell area: f64;
    cell perimeter: f64;

    relationship {
        (area, perimeter) := (width * height, 2.0 * (width + height));
    }
}

(a, b) := ... and the one-element (a,) := ... both destructure. Parenthesized binding targets require the first comma, so (a) := ... is invalid. A bare a := ... binds the right-hand side’s whole result (including a tuple-typed one) directly to the named cell. Each output’s declared type must structurally match its result.

Self-referencing methods

A self-referencing method reads a cell it also writes. During resolution, it reads that cell’s source value, not its previous derived value. The source remains separate from the computed correction, as it does for filters:

sheet clamp_via_relationship {
    cell level: i32 = 0;

    relationship {
        level := min(level, 0);
    }
}

Writing level stores its raw value. The next resolution applies the correction without overwriting that source.

Self-referencing methods must be idempotent

A self-referencing method must be idempotent: reapplying it to its corrected output leaves the output unchanged, f(f(x)) == f(x). min(level, 0) satisfies this: once level is at most 0, applying min again returns the same value.

The sheet author must ensure idempotence; neither construction nor propagation checks it. A non-idempotent operation, such as swapping two cells’ values, does not define a stable correction.