Tuple
In the prelude: every iyi program has it, with no import.
Tuple(*T)tuple
tuple Tuple(*T) < Value
# Two tuples are the same value when their members are. `Object#==` is
# false, so `{1, 2} == {1, 2}` was, and a tuple key was never found in a
# `Hash`. Member by member where one type holds the other, so `case {1,
# y} when {1, 2}` (y : Int32?) matches; `{-1}` and `{-1_i64}` are unequal.
def ==(other : Tuple(*U)) : Bool forall U
# Each member's own `===`: `when {Nil, Bool}` holds for `{nil, false}`,
# which `==` - a class against a value - never did.
def ===(other : Tuple(*U)) : Bool forall U
# Indexed by a *value* rather than by a literal, which is what walking a
# tuple at runtime needs: `std/indexable`'s `values_at` and `sprintf` do.
def [](index : Int32)
# And hashing follows equality: a key is found by its slot first and
# compared second, and `Object#hash` put every tuple in one slot. Each
# member multiplied through and its high bits folded back down: `a * 31 +
# b` gave the million points of a 1,000 by 1,000 grid 32,000 hashes, and
# a table probing a slot at a time had not filled in ten minutes.
def hash : Int32
def inspect : String
# How many: the type's own arithmetic, here rather than in `format.iyi`,
# where `std/indexable` could only reach it with a formatter compiled in.
def size : Int32
# A first member in braces of its own is spaced off, `{ {1, 2}, 3 }`, as the other library's is.
def to_s : String
end
A tuple written the way it is written:
{1, "a"}. The compiler lays a tuple out and answers[]; what it looks like printed is the prelude's, one element per position, each inspected.