diff --git a/SPEC.md b/SPEC.md index 1f8d2a8..bb770d5 100644 --- a/SPEC.md +++ b/SPEC.md @@ -481,10 +481,13 @@ All comparison operators accept two or more arguments and check the relation hol | Built-in | Description | |---|---| -| `==` | Structural equality. Works on any type. | +| `==` | Structural equality. Works on any type. Derived from `relate`. | | `!=` | Structural inequality. | | `<` | Numeric ordering. **Generic dispatch** for binary calls. For 3+ args, variadic fold checks all pairs. | | `<=` `>` `>=` | Numeric ordering. Derived from `<` and `==`. | +| `relate` | Structural diff + pattern match. See §11.0.1. **Operative.** | +| `pat` | Pattern constructor for `relate`. See §11.0.2. **Operative.** | +| `===` | Relational unification (miniKanren goal). See §11.0.3. **Operative.** | ### 7.3 Math @@ -772,6 +775,55 @@ The `error?` predicate (§7.11) returns `true` for error values. | Eval limit | `"eval-limit"` | `"message"` | | Internal | `"internal"` | `"message"` | +## 11. Structural Relation (`relate` and `pat`) + +`relate` and `pat` are two of Jest's 8 irreducible primitives. Together they subsume equality +testing and pattern matching in a single operation. + +### 11.0.1 `relate` — structural diff / pattern match + +``` +{"relate": [a, b, then, else]} +``` + +Operative (all four arguments unevaluated). Evaluates `a` and `b`, then: + +- **If `b` evaluates to a `{"pattern": ast}` value** (produced by `pat`): enters **pattern + matching mode**. Matches `ast` against the evaluated `a`. If the match succeeds, evaluates + `then` in a scope extended with the pattern's bindings. If it fails, evaluates `else`. + +- **Otherwise**: enters **equality mode**. Performs bidirectional structural matching between + the evaluated `a` and `b` (equivalent to `==`). If equal, evaluates `then`; otherwise `else`. + +`==` is derived: `{"==": [a, b]}` = `{"relate": [a, b, true, false]}`. +`let` is derived: `{"let": [bindings, body]}` uses `relate` in pattern mode to destructure. +`match` is derived: nested `relate` calls, one per clause. + +### 11.0.2 `pat` — pattern constructor + +``` +{"pat": expr} +``` + +Operative (argument unevaluated). Wraps the unevaluated expression as `{"pattern": expr}`, +which is a self-evaluating value. This tells `relate` to use pattern matching mode rather +than equality mode. + +### 11.0.3 `===` — relational unification (miniKanren) + +``` +{"===": [u, v]} +``` + +Applicative. Returns a miniKanren **goal** — a function from substitution to stream. Performs +relational unification of `u` and `v`: walks both through the current substitution, then +attempts structural unification. If unification succeeds, the goal produces a singleton stream +with the extended substitution; if it fails, the empty stream. + +Used within `run*` and `fresh` to build relational programs. Unlike `==` (which returns a +boolean) or `relate` (which branches), `===` produces a *constraint* that participates in +the relational search. + ## 11. Pattern Matching Jest provides structural pattern matching via `match`, `matches?`, `match-result`, first-class `pattern` values, and pattern combinators.