[unify:UnifyHandler, test_unify:TUHandler, ...]Handlers for operations which are not specified or those that are true/0 are ignored and never invoked. If Name is an existing extension, the specified handlers replace the current ones.
Whenever one of the specified operations detects an attributed variable, it will invoke all handlers that were declared for it and each of them receives either the whole attributed variable or its particular attribute as argument. The system does not check if the attribute that corresponds to a given handler is instantiated or not; this means that the handler must check itself if the attributed variable contains any attribute information or not. For instance, if an attributed variable X{a:_, b:_, c:f(a)} is unified with the attributed variable Y{a:_, b:_, c:f(b)}, the handlers for the attributes a and b should treat this as binding of two plain variables because their attributes were not involved. Only the handler for c has any work to do here. The library suspend.pl can be used as a template for writing attributed variable handlers.
The following operations invoke attributed variable handlers:
unify_handler(+Term, ?Attribute)The first argument is the term that was unified with the attributed variable, it is either a nonvariable or an attributed variable. The second argument is directly the contents of the attribute slot corresponding to the extension, i.e. it is not the whole attributed variable. When this handler is invoked, the attributed variable is already bound to Term.
If an attributed variable is unified with a standard variable, the variable is bound to the attributed variable and no handlers are invoked. If an attributed variable is unified with another attributed variable or a non-variable, the attributed variable is bound (like a standard variable) to the other term and all handlers for the unify operation are invoked. Note that several attributed variable bindings can occur e.g. during a head unification and also during a single unification of compound terms. The handlers are only invoked at certain trigger points (usually before the next predicate call).
test_unify_handler(+Term, ?Attribute)where the arguments are the same as for the unify handler. During the execution of the handler the attributed variable is bound to Term, however when all local handlers succeed, all bindings are undone.
instance_handler(-Res, ?TermL, ?TermR)and its arguments are similar to the ones of the compare_instances/3 predicate. The handler is invoked with one or both of TermL and TermR being attributed variables. The task of the handler is to compare the two terms and instantiate Res to either = or < (or fail if the result is >), according to the result of the comparison. All bindings made in the handler will be undone after processing the local handlers.
copy_handler(?AttrVar, ?Copy)AttrVar is the attributed variable encountered in the copied term, Copy is its corresponding variable in the copy. All extension handlers receive the same arguments. This means that if the attributed variable should be copied as an attributed variable, the handler must check if Copy is still a free variable or if it was already bound to an attributed variable by a previous handler.
suspensions_handler(?AttrVar, -ListOfSuspLists, -Tail)AttrVar is an attributed variable. The handler should bind ListOfSuspLists to a list containing all the attribute's suspension lists and ending with Tail.
delayed_goals_number_handler(?AttrVar, -Number)AttrVar is the attributed variable encountered in the term, Number is the number of delayed goals occurring in this attribute. Its main purpose is for the first-fail selection predicates, i.e. it should return the number of constraints imposed on the variable.
get_bounds_handler(?AttrVar, -Lwb, -Upb)The handler is only invoked if the variable has the corresponding (non-empty) attribute. The handler should bind Lwb and Upb to numbers (any numeric type) reflecting the attribute's information about lower and upper bound of the variable, respectively. If different attributes return different bounds information, get_var_bounds/3 will return the narrowest ones.
set_bounds_handler(?AttrVar, +Lwb, +Upb)The handler is only invoked if the variable has the corresponding (non-empty) attribute. Lwb and Upb are the numbers that were passed to set_var_bounds/3, and the handler is expected to update its own bounds representation accordingly.
print_handler(?AttrVar, -Attribute)AttrVar is the attributed variable being printed, Attribute is the term which will be printed as a value for this attribute, prefixed by the attribute name. If no handler is specified for an attribute, or the print handler fails, the attribute will not be printed.
The following handlers are still supported for compatibility, but their use is not recommened:
pre_unify_handler(?AttrVar, +Term)The first argument is the attributed variable to be unfied, the second argument is the term it is going to be unified with. This handler is provided only for compatibility with SICStus Prolog and its use is not recommended, because it is less efficient than the unify handler and because its semantics is somewhat unclear, there may be cases where changes inside this handler may have unexpected effects.
delayed_goals_handler(?AttrVar, ?GoalList, -GoalCont)AttrVar is the attributed variable encountered in the term, GoalList is an open-ended list of all delayed goals in this attribute and GoalCont is the tail of this list.
X{Attr}where Attr is the value obtained from the handler. If there are several handled attributes, all attributes are qualified like in
X{a:A, b:B, c:C}.An attributed variable X{m:a} with print handler =/2 can thus be printed in different ways, e.g.: 16.2
printf("%w", [X{m:a}]) or write(X{m:a}): X printf("%vMw", [X{m:a}]) or writeq(X{m:a}): _g246{suspend : _g242, m : a} printf("%mw", [X{m:a}]): X{a} printf("%Mw", [X{m:a}]): X{suspend : _g251, m : a} printf("%Vmw", [X{m:a}]): X_g252{a}
Write macros for attributed variables are not allowed because one extension alone should not decide whether the other attributes will be printed or not.