[comp.lang.prolog] Extensible Unification

micha@ecrc.de (Micha Meier) (06/13/91)

Several people have asked me if Sepia, which is claimed to be an extensible
Prolog system, allows the user to redefine the unification. Until the
version 3.0.15 this was possible only with sources (although easily :-)).
In the new release I have included a new data type - metaterms.
A metaterm is basically an atributed variable, like the one proposed e.g.
by U.Neumerkel (metastructure) or S. Le Huitouze (vara). The metaterms
in Sepia have been implemented using the coroutining and event mechanisms.

A metaterm looks like a normal variable, but it has an attribute,
which can be any Prolog term (even another metaterm) and which can
be accessed from it. Whenever the system tries to instantiate
a metaterm or to bind it to another metaterm, an event is raised
and the result of the binding is specified by a user-defined event handler.
Similarly, if a metaterm occurs in a built-in predicate, another event
is raised. In the event handler, the user can e.g. inspect the
attribute of the metaterm and modify it, or the metaterm variable
can be instantiated to some value, discarding the attribute, etc.

In this way, the user has a generic datatype whose processing is completely
specified by her/him. There are many ways of using metaterms, we are just
starting to recognize their full potential.

For example, variables whose values range over a specified domain
can be represented as metaterms, their attribute being the list
of the admissible values for the variable. When two variables
are unified, the handler makes the instersection of the two domains
and if there is only one element left, it instantiates them:

[sepia]: [user].
 meta_meta_unify(A, B) :-
      meta_term(A, DA),		% DA is the attribute of A
      meta_term(B, DB),
      intersection(DA, DB, DC), % compute the intersection of the two domains
      (DC = [Val] ->
            % only one value possible, bind the two variables
            meta_bind(A, Val),	% discard the attribute and bind the variable
            meta_bind(B, Val)
      ;
            meta_term(C, DC),	% create a new metaterm
            meta_bind(A, C),	% and bind the two variables to it
            meta_bind(B, C)
      ).
 user       compiled traceable 608 bytes in 0.02 seconds
 
yes.
% 10 is the event of unifying two metaterms
[sepia]: set_error_handler(10, meta_meta_unify/2).
 
yes.
[sepia]: meta_term(A, [yellow, blue, white, green]),
        meta_term(B, [orange, blue, red, yellow]), A = B.
 
A = <C-[yellow, blue]>		% the metaterm is printed using portray/2
B = <C-[yellow, blue]>
yes.
[sepia]: meta_term(A, [yellow, blue, white, green]),
        meta_term(B, [orange, blue, red, black]), A = B.
 
A = blue
B = blue
yes.

When, on the other hand, the variable is being instantiated, the event handler
checks if the value is permitted, and if so, it instantiates it:

[sepia]: [user].
 meta_term_unify(Meta, Term) :-
      meta_term(Meta, Type),
      memberchk(Term, Type),
      meta_bind(Meta, Term).
    user       compiled traceable 216 bytes in 0.00 seconds

yes.
% 11 is the event of unifying a metaterm with a nonvariable
[sepia]: set_error_handler(11, meta_term_unify/2).
 
yes.
[sepia]: meta_term(A, [yellow, blue, red]), A = red.
 
A = red
yes.
[sepia]: meta_term(A, [white, lila, pink, grey]), A = blue.

no (more) solution.                                          

There are various possible uses for metaterms:

	- A static attribute of a variable. An example is the source
 	  name of the variable (in Sepia the source names are kept
	  using the same mechanism, but more directly).

	- A dynamic attribute - e.g. a list of goals that have
 	  to be executed when the variable becomes (more) instantiated.
	  Typically, coroutining can be implemented on top of metaterms.

	- Generic data types with run-time type testing, like the example above.

	- Constraint propagation. The attribute can represent the domain
	  of the variable and a list of constraints to be evaluated
	  when the domain is updated. For example, constraint propagation
	  over finite domains can be very easily implemented
	  by representing the domain as a list of values (or numeric
	  intervals), and constraints can be suspended using the
	  normal delaying mechanism of Sepia.

	- A term which contains metaterms can be seen as a potential
	  representation of many other terms (instances) and depending
	  on the context where it is used, it is interpreted as
	  the corresponding one. For example, when mixing a metaprogram
	  with the object program, there are usually some difficulties
	  as to how to represent the object variables. If they are
	  metaterms, they can be treated as ground terms by
	  the metaprogram and as variables in reflection to the object level.

It is also important to note that there is no performance penalty
when not using the metaterms, and processing the metaterms themselves
is also quite efficient, because the underlying WAM of Sepia has
been written with similar extensions in mind.

Sepia, which is a complete, compiler-based Unix Prolog system, includes
various other advanced features, including a high-level debugging
tool Opium, graphics, C interface and extensive documentation.
ECRC will be demonstrating Sepia and other interesting systems at the
ICLP'91 exhibition in Paris.

--Micha


E-MAIL  micha@ecrc.de            	MAIL	Micha Meier
Tel. +49-89-92699-108				ECRC, Arabellastr. 17
Fax  +49-89-92699-170  				8000 Munich 81
						Germany
--
E-MAIL  micha@ecrc.de            	MAIL	Micha Meier
Tel. +49-89-92699-108				ECRC, Arabellastr. 17
Fax  +49-89-92699-170  				8000 Munich 81
						Germany