This package implements attributed variables in the style of Holzbaur [Hol90]. It provides a way to associate to variables one or several arbitrary terms called attributes. By allowing the user to redefine the unification of attributed variables, this extension makes possible the design of coroutining facilities (see subsection Example) and clean interfaces between Prolog and constraints solvers.
Attributes are private to module and each variable can have at most one attribute in each module. Attributes are handled by predicate provided by attr_rt module.
attr package imports automatically attributes variables manipulation predicates, put_attr_local/2, get_attr_local/2, and del_attr_local/2 from module 'attr/attr_rt', and set up the following hooks:
Hook that must be defined in the module using package attr. It is called after the attributed variable of that module 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. Normally this predicate fails to veto binding the variable to VarValue, forcing backtracking to undo the binding. If VarValue is another attributed variable the hook often combines the two attribute and associates the combined attribute with VarValue using attr_rt:put_attr_local/2.
This optional hook, if it is defined, is used by attr_rt:copy_term/3 to project attributes of that module to residual goals, and by the toplevel to obtain residual goals after executing a query. The predicate is supposed to unified S0 with a different list containing the residual goals and which have S as tail. For the sake of simplicity, it can be defined using dcg. (See DCG non-terminal attribute_goal(Var) in example below.)
Called by write_term/2 for each attribute associate to the variable Var if the option option attributes(portray) is in effect. If the hook succeeds the variable is considered to be printed otherwise Module =... is printed to indicate the existence of an attribute defined in module Module. At call time Attribute is the actual value of the attribute associate to the variables Var.
In the following example we give an implementation of freeze/2. We name it myfreeze/2 in order to avoid a name clash with the built-in predicate of the same name. The code is available in the module library(attr/example/myfreeze)
:- module(myfreeze, [myfreeze/2], [attr, dcg, hiord]). :- use_module(engine(io_basic)). :- meta_predicate(myfreeze(?, goal)). myfreeze(X, Goal) :- ( nonvar(X) -> call(Goal) ; get_attr_local(X, Fb) -> meta_conj(Fb, Goal, C), put_attr_local(X, C) % rescue conjunction ; put_attr_local(X, Goal) ). :- if(defined(optim_comp)). attr_unify_hook(Fa, Other) :- ( nonvar(Other) -> '$trust_metatype'(Fa, goal), call(Fa) ; get_attr_local(Other, Fb) -> meta_conj(Fa, Fb, C), put_attr_local(Other, C) % rescue conjunction ; put_attr_local(Other, Fa) % rescue conjunction ). :- else. attr_unify_hook(Fa, Other) :- ( nonvar(Other) -> call(Fa) ; get_attr_local(Other, Fb) -> meta_conj(Fa, Fb, C), put_attr_local(Other, C) % rescue conjunction ; put_attr_local(Other, Fa) % rescue conjunction ). :- endif. attribute_goals(X) --> [myfreeze:myfreeze(X, G)], {get_attr_local(X, G)}. attr_portray_hook(G, Var):- display(Var), display('<-myfrozen('), display(G), display(')'). % A (meta) conjunction of two goals meta_conj('$:'(Fa), '$:'(Fb), '$:'('basiccontrol:,'(Fa, Fb))).