set/union
===============================================================================

%% Union of two sets (stable insertion order)

1. Usage
-------------------------------------------------------------------------------

```mech:disabled
C := set/union(A, B)
C := A ∪ B
```

2. Description
-------------------------------------------------------------------------------

Computes the union of two sets A and B, returning every distinct element that appears in either input. The implementation wraps a Rust `IndexSet::union` iterator, so the result preserves stable insertion order:

- All elements from `A` appear first in `A`'s order.
- Then any elements from `B` that are not already in `A` are appended in `B`'s order.

3. Input
-------------------------------------------------------------------------------

Arguments:
- `A` : set of T (or an array treated as a set; duplicates ignored)
- `B` : set of T (or an array treated as a set; duplicates ignored)

Element type constraints:
- T must be hashable and comparable for equality (Eq and Hash in Rust).
- Common element kinds include integers, strings, symbols, and booleans.

4. Output
-------------------------------------------------------------------------------

Result:
- `C` : set of T containing all unique elements from `A` and `B`, ordered with `A` first
  and then any new elements from `B`.

5. Examples
-------------------------------------------------------------------------------

(5.1) Simple union of two small sets

```mech:ex1
A := {"a", "b", "c"}
B := {"b", "c", "d"}
C := A ∪ B
```

(5.2) Duplicates in inputs are ignored

```mech:ex2
A := {1, 2, 2, 3}
B := {2, 4, 4}
C := A ∪ B
```

(5.3) Order is stable by first appearance (IndexSet semantics)

```mech:ex3
A := {"x", "y"}
B := {"y", "x", "z"}
C := A ∪ B
```

6. Details
-------------------------------------------------------------------------------

Set semantics:
- Inputs are coerced to sets by dropping duplicates using hash and equality.
- The result contains each distinct element exactly once.

Stable insertion order:
- Matches Rust IndexSet behavior: iteration order reflects first insertion.
- A determines the ordering of shared elements; new elements come from B in their original order.

Performance:
- Average O(\|A\| + \|B\|) time with hashing; memory is O(\|A\| + \|B\|) for the union.

Determinism:
- Given equal inputs, output order is deterministic across runs and platforms because it derives from insertion order rather than raw hash iteration order.

7. Errors
-------------------------------------------------------------------------------

- Incorrect number of arguments (expects exactly two).
- Unsupported element type (not hashable or not comparable for equality).
- Inconsistent element kinds between A and B.
