# `Monty.Config.Target`
[🔗](https://github.com/d-led/ex.tbp.monty/blob/v0.1.0/packages/ex_tbp_monty_core/lib/monty/config/target.ex#L1)

The Elixir module a `_target_` names.

Monty's Hydra configs build objects by naming classes:

     policy:
       _target_: tbp.monty.frameworks.models.motor_policies.SurfacePolicyCurvatureInformed
       alpha: 0.1

Composing that config keeps the name (`Monty.Config.Resolvers` returns
`${monty.class:...}` as a dotted path), so building the object means turning
that path into a module here — through `Monty.ModuleMap`, which is generated
from Monty's source and therefore knows whether the class is ported at all.

A class this port has not written is an error rather than a silent stand-in:
a run built from a config must be a run of *that* config, and a policy that
quietly became something else would make the experiment a lie.

# `class!`

```elixir
@spec class!(map() | String.t()) :: module()
```

The module `config` targets.

Accepts a config map with `_target_`, or the dotted path on its own.

# `implemented?`

```elixir
@spec implemented?(term()) :: boolean()
```

Whether every `_target_` in a config tree names a module this port has.

Only the strings that name a class are looked at: a config's parameters are
mostly ordinary strings (`agent_id_0`, `all`), and treating those as class
names would call every experiment unbuilt.

# `unwrap`

```elixir
@spec unwrap(String.t()) :: String.t()
```

The dotted path inside a `${monty.class:...}` interpolation, or the value.

Composition resolves interpolations, but a config may reach a builder before
it has been through `Monty.Config.Resolvers` — a config written by hand in a
test, for instance — so both forms are accepted.

---

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