🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.prolog
Article #3253

oops

#3253
From: Jason Trenouth
Date: Fri, 15 Apr 1988 17:05
140 lines
6065 bytes
A while back somebody asked about object-orientated programming (theories,
modules, etc) in Prolog (can't remember who). Anyway here's some food for
thought.

If you're a Quintus Prolog 2.0 (or later version) user then you've already got
an OOPS (object-oriented programming system).... you didn't know that?... you
can't find it in the manual?... never fear, your saviour is here!

[I can just feel ROK looking down his nose at this article already...(presses
on with the stiffest of upper lips)...]

The latest versions of Quintus Prolog come with a module system. This allows
the partitioning of a program into separate name spaces. It also provides for
importing and exporting of predicates between modules just like a good module
system should. So far so good. It ALSO lets the programmer access any
predicate directly: bypassing the nice protection of importing and exporting
that's just been mentioned. Surely this is bad? Not so. It is just the
loophole that we need to build a toy OOPS.

[...(dons an asbestos suit to give protection against ROK's flames for
mentioning a Quintus product again)...]

By prepending the module name to a predicate we can reference it anywhere. Say
the module "william" contained a predicate called "third_edition" then we can
reference it by:

	william:third_edition(...args...)

How do we go about building our OOPS? Well, the simplest way is to introduce
the idea of delegation between modules (theories, objects, frames,...). If we
ask a module to solve a query and it fails, then we would like the query to be
delegated to another module. Our first stab might be something like this:

	solve(Goal, Module) :-
		Module:call(Goal).
	solve(Goal, Module) :-
		Module:delegate(SuperModule),
		solve(Goal, SuperModule).

Here our solver will try the original module first before looking for a
"delegate" clause.  Does this work? Well, sort of. Lets look at an example:

:- module(human, []).

	arms(2).
	legs(2).

:- module(ehud, []).

	delegate(human).
	arms(1).

[Ignore the fact that these have to be in individual files (for the moment).]

Now if we query the "ehud" module about "arms" then we will get the local
value of 1. However, if we query the "ehud" module about "legs" then the query
is delegated to the "human" module, and we get the answer 2.. So far, so good.
What about methods?  What? Methods. If this is to be anything more than a data
hierarchy then we would like to be able to have procedures in the modules.
Let's put the following definition in the "human" module:

	limbs(X) :-
		arms(Y),
		legs(Z),
		X is Y + Z.

Now suppose that we query the "ehud" module about "limbs". Splat! The solver
falls flat on its face and comes up with the answer 4. The reason is that it
evaluates the procedure in the "human" module environment. How can we get
round this? Somehow we need to tell "limbs" about where the query has come
from originally. This means that we need to be in control of the execution,
which leads us to... a good ol', all singin', all dancin',... meta
interpreter!

% interface which remembers original module queried.
% "wrt" is sort for "with respect to".

	solve(Goal, Module) :-
		solve_wrt_module(Goal, Module, Module).

% either it's a conjunction of goals,
% a built in predicate,
% a call to solve itself (message passing),
% a goal which can be replaced by a conjunction of subgoals, or
% something that needs to be delegated to a another module.

	solve_wrt_module((Goal1, Goal2), Module, Original) :-
		!,
		solve_wrt_module(Goal1, Module, Original),
		solve_wrt_module(Goal2, Module, Original).
	solve_wrt_module(Goal, _, _) :-
		predicate_property(Goal, built_in),
		!,
		call(Goal).
	solve_wrt_module(solve(Goal, OtherModule), _, _) :-
		!,
		solve(Goal, OtherModule).
	solve_wrt_module(Goal, Module, Original) :-
		predicate_property(Module:Goal, _),
		clause(Module:Goal, Body),
		solve_wrt_module(Body, Original, Original). % important bit
	solve_wrt_module(Goal, Module, Original) :-
		predicate_property(Module:delegate(_), _),
		Module:delegate(SuperModule),
		solve_wrt_module(Goal, SuperModule, Original).

[comments on style, bugs, etc welcome]

With this interpreter, the above example query comes back with the correct
answer of 3 arms. Like the first it also handles multiple delegations. These
are searched depth first (like Flavors) by Prolog's backtracking; which
incidentally violates some inheritance properties - you can't have everything!

One question must be: where are the classes and instances? Er,... there just
aren't any. In Flavors (and Smalltalk) classes contain the methods and some
data, and act as templates. These are then used to create instances, which
contain a copy of the data. This is an unnecessary restriction on object
orientated programming. The system above (POOPS?) and others (eg CommonOrbit)
have only one type of object (called a "prototype" in CommonOrbit), which can
be used more flexibly.

For more information on OOPSs, and a comparison between CommonOrbit and
Flavors, see "Artificial Intelligence Programming Environments" edited by R.
Hawley (Ellis Horwood, 1986).

Chow.

	_______________________________________
	|                                     |
	| Jason Trenouth                      |
	|  Computer Science Department        |
	|   University of Exeter              |
	|    Devon EX4 4PT                    |
	|     United Kingdom                  |
	|                                     |
	| JANET:  jtr@uk.ac.exeter.cs         |
	| UUCP:   jtr@expya.uucp              |
	| BITNET: jtr%uk.ac.exeter.cs@ukacrl  |
	|_____________________________________|
Technical Details
Message-ID: <422@expya.UUCP>
Path: arc1-ca.pugleaf.net!utzoo!mnetor!uunet!mcvax!ukc!warwick!expya!jtr

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!mnetor!uunet!mcvax!ukc!warwick!expya!jtr
From: jtr@expya.UUCP (Jason Trenouth)
Newsgroups: comp.lang.prolog
Subject: oops
Message-ID: <422@expya.UUCP>
Date: 15 Apr 88 17:05:48 GMT
Reply-To: jtr@expya.UUCP (Jason Trenouth)
Organization: Computer Science Dept. - University of Exeter. UK
Lines: 140