# `Yarnspinnex.Vars`
[🔗](https://github.com/atavistock/yarnspinnex/blob/main/lib/yarnspinnex/vars.ex#L1)

Name lookup shared by the interpreter and `Yarnspinnex.Ops`: `$player` finds `"player"` or
`:player` in a map or `Yarnspinnex.Projection`, string key first. A keyword list is accepted at
the top level only, as context (`lookup!/1`) or vars (`normalize/1`); nested values are maps.

# `collection`

```elixir
@type collection() ::
  %{optional(atom() | String.t()) =&gt; term()}
  | keyword()
  | Yarnspinnex.Projection.t()
```

What a host may pass as context: read by name, never copied or rewritten.

# `lookup`

```elixir
@type lookup() ::
  %{optional(atom() | String.t()) =&gt; term()} | Yarnspinnex.Projection.t()
```

What `fetch/2` reads: a context or field value after `lookup!/1`.

# `vars`

```elixir
@type vars() :: %{optional(atom() | String.t()) =&gt; term()} | keyword()
```

What a host may pass as variables: normalized once into the cursor.

# `fetch`

```elixir
@spec fetch(lookup(), String.t()) :: {:ok, term()} | :error
```

Looks `name` up as a string key, then as an existing atom; `:error` when neither is there.

# `lookup!`

```elixir
@spec lookup!(term()) :: lookup()
```

The host's `context` as `fetch/2` reads it: a map or `Yarnspinnex.Projection` as is, a keyword
list as a map. Raises on anything else, a domain struct included.

# `normalize`

```elixir
@spec normalize(vars()) :: %{optional(String.t()) =&gt; term()}
```

Builds the string-keyed variable map a cursor carries from a map or keyword list.

---

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