A fragment used at a position (spec/14 §19.3, D-101).
A layer in a composite and an entry in a style stack are the same thing: a use of a
fragment at a site. The site has four parts, each written by exactly one surface, and
they are applied in one order — ref → local → mask → bind → stack — so a mask removes
what the site would otherwise say whichever part said it, and a bound variable is
renamed before the cascade sees it wherever at the site it stands. A site the host
seeded is nothing but its local, and is masked and bound like any other.
%Visualize.Chart.Use{
id: {:use, 7}, # this site's own identity (§19.3)
ref: {:style, 11}, # which fragment (§19.2); nil for an inline-only site
mask: [:stroke], # removed here, so a lower layer shows through (§19.5)
vars: %{color: var(:color_1)}, # what the fragment's variables mean here (§19.4)
local: %{opacity: 0.8}, # added or overridden here
origin: nil # the entry an unlocked site came from (#381)
}A struct is a leaf of every walk (D-92), which is what keeps Visualize.Chart.stack/1
from descending into a site and merging its parts.
Examples
iex> alias Visualize.Chart.Use
iex> use = Use.new({:style, 11})
iex> {use.ref, use.mask, use.vars, use.local}
{{:style, 11}, [], %{}, %{}}
iex> Visualize.Chart.Use.new({:style, 2}, [Visualize.Chart.Use.new({:style, 1})]).id
{:use, 2}
Summary
Types
A site's own identity: unique within the composite that holds it.
A path into a fragment: the keys from its root, as Visualize.Chart.explain/1 gives them.
Functions
A fragment with its variables substituted (spec/14 §19.4, D-102).
A fragment with paths removed (spec/14 §19.5).
A use of a fragment with a fresh id and the three empty parts (spec/14 §19.3).
A use over a body it has already been given: the local node cascaded over it, the mask
over the result, and the bindings over all of it — everything resolve/2 does after the
fetch (spec/14 §19.3). Mask and bind run after local so they speak for everything the
site contributes: an inline-only site is nothing but its local, and is masked and bound
like any other. A mask of everything is the whole site removed — that is what disabling
a layer means.
A use site resolved to the fragment it stands for, in order: the referenced body, the mask, the bindings, and the local node cascaded over it (spec/14 §19.3).
Types
@type id() :: {:use, pos_integer()}
A site's own identity: unique within the composite that holds it.
@type path() :: [atom() | non_neg_integer()]
A path into a fragment: the keys from its root, as Visualize.Chart.explain/1 gives them.
@type t() :: %Visualize.Chart.Use{ id: id(), key: atom() | nil, local: map(), mask: [path() | atom()], origin: Visualize.Chart.Fragment.id() | nil, ref: Visualize.Chart.Fragment.id() | nil, vars: %{required(atom()) => term()} }
Functions
A fragment with its variables substituted (spec/14 §19.4, D-102).
Every %Var{name: k} becomes the map's value for k — a literal, or another var/1,
which is a rename — and a variable the map does not name is left as it is. The result is
a fragment with fewer, or differently named, variables in it, which every existing rule
already accepts. Any other struct is a leaf.
iex> Visualize.Chart.Use.bind(%{fill: Visualize.Chart.var(:color)}, %{color: "blue"})
%{fill: "blue"}
iex> fragment = %{fill: Visualize.Chart.var(:color), text: [Visualize.Chart.var(:unit)]}
iex> Visualize.Chart.Use.bind(fragment, %{color: Visualize.Chart.var(:color_1)})
%{fill: %Visualize.Chart.Var{name: :color_1}, text: [%Visualize.Chart.Var{name: :unit}]}
A fragment with paths removed (spec/14 §19.5).
A path is the keys from the fragment's root; a bare atom is a path of one. A path the
fragment does not carry removes nothing. Masking :all removes everything, which is
what disabling a layer is (D-87 restated in §19.3).
iex> Visualize.Chart.Use.mask(%{stroke: "#111", stroke_width: 5}, [:stroke])
%{stroke_width: 5}
iex> Visualize.Chart.Use.mask(%{frames: %{main: %{legend: %{}, margin: %{}}}}, [[:frames, :main, :margin]])
%{frames: %{main: %{legend: %{}}}}
iex> Visualize.Chart.Use.mask(%{a: 1}, :all)
%{}
@spec new(Visualize.Chart.Fragment.id() | nil, [t()]) :: t()
A use of a fragment with a fresh id and the three empty parts (spec/14 §19.3).
The id is one more than the highest among among — the sites this one will sit beside —
so it is unique within its composite. A site's identity needs no more scope than that:
nothing outside the composite refers to a site.
A use over a body it has already been given: the local node cascaded over it, the mask
over the result, and the bindings over all of it — everything resolve/2 does after the
fetch (spec/14 §19.3). Mask and bind run after local so they speak for everything the
site contributes: an inline-only site is nothing but its local, and is masked and bound
like any other. A mask of everything is the whole site removed — that is what disabling
a layer means.
@spec resolve(t(), (Visualize.Chart.Fragment.id() -> {:ok, map()} | :error)) :: {:ok, map()} | {:missing, Visualize.Chart.Fragment.id(), map()}
A use site resolved to the fragment it stands for, in order: the referenced body, the mask, the bindings, and the local node cascaded over it (spec/14 §19.3).
fetch is how the referenced body is found — a store's get, or any function of an id —
and returns {:ok, fragment} or :error. A ref the fetch cannot find is a mask of
everything: the site stands for its local node alone, and the id is returned so the
caller can say so (§19.2, D-100). A nil ref is an inline-only site.