jonnify·bcs /bcs/elixir-core/archetypes/composition-is-a-fold

B2.4.2 · dive 2 of 3 · module B2.4

Composition is a pure fold.

compose/2 folds the :extends chain with Map.merge — base first, descendants after, overrides last; resolve/3 keeps it pure by taking an injected fetch. The view is built at read time.

The chain walked root-first, reduced with Map.merge, overrides applied last. Select a part.
walk :extends root-first via fetchrootparentchild Enum.reduce(chain, Map.merge)base first, descendants override entity overridescomposed map — overrides win last:extends dropped
readout · Select a part. resolve/3 walks the :extends chain root-first via an injected fetch; compose/2 reduces it with Map.merge so descendants override; overrides win last.
§1

The idea

echo_data · bcs/archetypes.ex

The composed view does not exist until it is read. compose/2 takes a chain of bundles and a map of overrides, folds the chain with Map.merge — base first, each descendant after — then merges the overrides last and drops the :extends key. Right-most wins: a descendant overrides its parent, and the entity’s overrides override them all.

Resolution stays pure by taking its boundary as an argument. resolve/3 walks the :extends chain root-first through a fetch function the caller supplies, then hands the chain to compose/2; whether fetch reads a property store or a snapshot, the composing logic is the same pure fold. The side effect is injected, so the merge itself touches nothing outside its arguments.

Codemojex composes a tile’s effective properties at the moment it needs them. The base tile, the power-up that extends it, and the placed tile’s overrides fold into one map on read — not stored pre-merged, not stale when the base changes. Change the base bundle and every entity that extends it shows the change the next time it is composed.

§4

The doors

the sibling courses
§2

References

sources · related

Sources

Related