tuple
===========================================================================

%% A `tuple` is an ordered collection of elements, potentially of heterogeneous kinds, similar to a fixed-length list.

1. Syntax
-------------------------------------------------------------------------------

Tuples are defined using parentheses `()` with elements separated by commas.

```
(1, true)
("Hello", 42, false)
(1, ("Hello", false))
```

When parsed and rendered, this code will appear as:

```mech:disabled
(1, true)               -- two-tuple of f64 and bool
("Hello", 42, false)    -- three-tuple of string, f64, and bool
(1, ("Hello", false))   -- nested tuple
```

(!)> There is no such thing as a single-element tuple in Mech. A single value in parentheses is just that value. For example, `(42)` is just `42`, not a one-tuple containing `42`.

2. Kind
-------------------------------------------------------------------------------

The kind of a tuple is determined by the kinds of its elements. For example:

```mech:disabled
(1, true)       -- kind: {{<(f64,bool)>}}
("Hello", 42)   -- kind: {{<(string,f64)>}}
```

Tuples can be nested, and the kind reflects the structure:

```mech:disabled
(1, ("Hello", false)) -- kind: {{<(f64,(string,bool))>}}
```

3. Construction
-------------------------------------------------------------------------------

There are two ways to construct tuples:

- Tuple literals
- Comprehensions

(3.1) Tuple Literals

```mech:ex 3.1
q := (10, "b", true)
nested := (1, ("Hello", false))
```

(3.2) Comprehensions

Tuples can be constructed using comprehensions:

```mech:ex 3.2
x := {1, 2, 3}
y := {4, 5}
{(a, b) | a <- x, b <- y}
```

The above comprehension generates a set of tuples containing all combinations of elements from sets `x` and `y`.

4. Accessing Elements
-------------------------------------------------------------------------------

Elements can be accessed in two ways:

- Dot access
- Destructuring

(4.1) Dot Access


Tuple elements are accessed by their 1-based index using the `.` operator.

```mech:ex 4.1
q := (10, "b", true)
q.1
```

Similarly:

```mech:ex 4.1
q.2
```

Nested tuples are accessed recursively:

```mech:ex 4.2
nested := (1, ("Hello", false))
nested.2 -- Access the second element, which is a tuple
```

To access elements within the nested tuple:

```mech:ex 4.2
nested.2.1 -- Access "Hello"
```

(4.2) Destructuring

Tuples can be destructured into variables:

```mech:ex 5.1
a := (10, 11, 12)
(x, y, z) := a
x + y + z
```

Destructuring works recursively for nested tuples:

```mech:ex 5.2
nested := (1, ("Hello", false))
(a, (b, c)) := nested
a   -- 1
b   -- "Hello"
c   -- false
```

6. Assigning Elements
----------------------------------------------------------------------------

Mutable tuples allow assignment via dot indexing:

```mech:ex 6.1
~q := (10, "b", true)
q.1 = 42   -- Updates the first element
q
```

Immutable tuples cannot be modified. The following code raises an error:

```mech:disabled
q := (10, "b", true)
q.1 = 42   -- Error: cannot assign to element of immutable tuple
```