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