Skip to content

Anonymous tuples / pairs with destructuring (deferred design decision) #617

@aallan

Description

@aallan

Vera version: vera 0.0.138
Origin: Friction surfaced while writing terminal Tetris on Vera 0.0.138.

Problem

Vera has Array<T> and ADTs but no anonymous tuples. Returning (dx, dy) from a piece-offset lookup four times per piece (Tetris) currently has three options:

  1. Flat Array<Int> of length 8 per (kind, rotation), with [2*i] being x and [2*i+1] being y. The Tetris implementation used this — and it's the worst option, because the indexing arithmetic is exactly the kind of thing that triggers #615 (non-contiguous Int slot capture) in closures.
  2. A data Pair { Pair(Int, Int) } ADT just for this purpose. Works, but every use site needs a match, which pushes more slots, which means more slot-index reasoning.
  3. A two-element Array<Int>. Same problem as (1), shorter syntax.

A built-in (Int, Int) with destructuring (let (x, y) = ...) would be the obviously-right answer — saves both the slot-counting effort and removes one of the bug-trigger sites for #615.

Proposed (sketch — needs design)

-- Type: (T1, T2, ...) anonymous product
private fn piece_offset(@Kind, @Rot, @Int -> @Tuple<Int, Int>)
  requires(true) ensures(true) effects(pure)
{
  ...
}

-- Construction
let @Tuple<Int, Int> = (3, 5);

-- Destructuring in let
let (@Int, @Int) = piece_offset(@Kind.0, @Rot.0, @Int.0);
-- @Int.0 = y (most recent, per De Bruijn convention), @Int.1 = x

-- Field access (alternative)
@Tuple<Int, Int>.0.first   -- or .0 / .1 / etc

Open design questions

The friction document explicitly flags that this is "probably a bigger language change than it looks":

  • The slot system has clean answers for ADTs and arrays; tuples need their own slot-stack story.
  • Tuple destructuring in let bindings interacts with the De Bruijn convention — does let (x, y) = ... push two slots in left-to-right order (consistent with field declaration order) or right-to-left (consistent with parameter ordering)?
  • Overlap with single-variant ADTs: the language already lets you write data Pair<A, B> { Pair(A, B) } and pattern-match. Does (A, B) desugar to that? Or is it a distinct kind?

The friction document concludes: "Tuples are tempting but probably a bigger language change than it looks. I'd rather have the rest of [the friction list] first."

Priority

Speculative / deferred decision — design first, no implementation until the language-change question is resolved. Filed primarily so the friction is captured rather than redirecting to "use ADTs"; if a tuples PR lands later, the discussion thread is here.

Origin

Friction document from terminal Tetris experiment.

Metadata

Metadata

Assignees

No one assigned

    Labels

    designFuture language design (spec §0.8)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions