7.1.2 Attributed variable hooks
Attribute names are linked to modules. This means that certain operations on attributed variables cause hooks to be called in the module whose name matches the attribute name.
- attr_unify_hook(+AttValue, +VarValue)
- A hook that must be defined in the module to which an attributed
variable refers. It is called after the attributed variable has
been unified with a non-var term, possibly another attributed variable.
AttValue is the attribute that was associated to the variable
in this module and VarValue is the new value of the variable.
If this predicate fails, the unification fails. If VarValue
is another attributed variable the hook often combines the two
attributes and associates the combined attribute with VarValue
using
put_attr/3.
- To be done
- The way in which this hook currently works makes the implementation of
important classes of constraint solvers impossible or at least extremely
impractical. For increased generality and convenience, simultaneous
unifications as in
[X,Y]=[0,1]
should be processed sequentially by the Prolog engine, or a more general hook should be provided in the future. See Triska, 2016 for more information.
- attribute_goals(+Var)
//
- This nonterminal is the main mechanism in which residual constraints are
obtained. It is called in every module where it is defined, and
Var has an attribute. Its argument is that variable. In each
module, attribute_goals//1
must describe a list of Prolog goals that are declaratively equivalent
to the goals that caused the attributes of that module to be present and
in their current state. It is always possible to do this (since these
attributes stem from such goals), and it is the responsibility of
constraint library authors to provide this mapping without exposing any
library internals. Ideally and typically, remaining relevant attributes
are mapped to pure and potentially simplified Prolog goals that
satisfy both of the following:
- They are declaratively equivalent to the constraints that were
originally posted.
- They use only predicates that are themselves exported and documented in the modules they stem from.
The latter property ensures that users can reason about residual goals, and see for themselves whether a constraint library behaves correctly. It is this property that makes it possible to thoroughly test constraint solvers by contrasting obtained residual goals with expected answers.
This nonterminal is used by copy_term/3, on which the Prolog top level relies to ensure the basic invariant of pure Prolog programs: The answer is declaratively equivalent to the query.
Note that instead of defaulty representations, a Prolog list is used to represent residual goals. This simplifies processing and reasoning about residual goals throughout all programs that need this functionality.
- They are declaratively equivalent to the constraints that were
originally posted.
- project_attributes(+QueryVars, +ResidualVars)
- A hook that can be defined in each module to project constraints on newly introduced variables back to the query variables. QueryVars is the list of variables occurring in the query and ResidualVars is a list of variables that have attributes attached. There may be variables that occur in both lists. If possible, project_attributes/2 should change the attributes so that all constraints are expressed as residual goals that refer only to QueryVars, while other variables are existentially quantified.
- [deprecated]attr_portray_hook(+AttValue, +Var)
- Called by write_term/2
and friends for each attribute if the option
attributes(portray)
is in effect. If the hook succeeds the attribute is considered printed. OtherwiseModule = ...
is printed to indicate the existence of a variable. This predicate is deprecated because it cannot work with pure interface predicates like copy_term/3. Use attribute_goals//1 instead to map attributes to residual goals.