# `PtcRunner.Lisp.Eval.Patterns`
[🔗](https://github.com/andreasronge/ptc_runner/blob/main/lib/ptc_runner/lisp/eval/patterns.ex#L1)

Pattern matching for let bindings in Lisp evaluation.

Handles destructuring patterns including variables, map destructuring,
sequence destructuring, and :as patterns.

# `bindings`

```elixir
@type bindings() :: %{required(atom()) =&gt; term()}
```

# `match_result`

```elixir
@type match_result() :: {:ok, bindings()} | {:error, {:destructure_error, String.t()}}
```

# `pattern`

```elixir
@type pattern() :: term()
```

# `coerce_for_pattern`

```elixir
@spec coerce_for_pattern(pattern(), term()) ::
  term() | {:error, {:destructure_error, String.t()}}
```

Coerces a value to match the expected shape of a pattern.

Used for rest-arg keyword arguments: when a variadic rest pattern expects map
destructuring, converts a flat key-value list to a map. Returns an error tuple
for odd-length lists. Returns the value unchanged for non-map patterns.

## Examples

    iex> pattern = {:destructure, {:keys, [:a], []}}
    iex> PtcRunner.Lisp.Eval.Patterns.coerce_for_pattern(pattern, [:a, 1])
    %{a: 1}

    iex> PtcRunner.Lisp.Eval.Patterns.coerce_for_pattern({:var, :xs}, [1, 2])
    [1, 2]

# `match_pattern`

```elixir
@spec match_pattern(pattern(), term()) :: match_result()
```

Matches a pattern against a value, returning variable bindings on success.

# `match_zipped`

```elixir
@spec match_zipped([pattern()], [term()]) :: match_result()
```

Match `patterns` against `values` pairwise via `Enum.zip/2`, merging the
bindings and halting on the first error.

Unlike `match_positional/2`, `Enum.zip/2` truncates to the shorter list, so
this is for callers (function-arg and `recur` binding) whose arities are
already validated to line up. Shared by `Eval.Apply` and `Eval`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
