[comp.lang.prolog] Object-oriented system in Prolog

johnson@csli.STANFORD.EDU (Mark Johnson) (06/13/88)

/* 
Finally a comment on my toy OOPS!!!

> From: gandalf@csli.STANFORD.EDU (Juergen Wagner)
> ...  the program oversimplifies inheritance by just
> 	o  specifying properies of graph nodes,
> 	o  disallowing the inheritance of certain properties, and
> 	o  walking through in depth-first.
> A *REAL* object-oriented system should at least be able to handle
> examples like the following correctly... 
> 
>     truck is_a object.
>     toy is_a object.
> 
>     toytruck is_a toy.
>     toytruck is_a truck.
> 
>     tt is_a toytruck.
> 
>     purpose(object, nil).
>     purpose(truck, transport).
> 
>     find_purpose(X,V) :-
> 	    inherits(X, purpose, Super),
> 	    purpose(Super, V).
> 
> For the query
>     find_purpose(tt, X)
> this will generate the solutions
>     nil
>     transport
>     nil
> which reveals the deficiency of such an algorithm. It is desirable to
> get the solutions
>     transport
>     nil
> only, because the "transport" property is defined in a more
> specialized super-class of "toytruck" than "nil". Therefore, we need
> some strategy tranversing nodes iff all relevant daughters have
> already been searched.

  ... a bunch of code deleted...

Hmm.  Declaratively speaking, the solutions { nil, transport, nil }
and { transport, nil } are the same set of solutions.  

But I think the criticism is valid - particularly since the redundancies
are fairly easily avoided by defining find_purpose as follows:

find_purpose(X,V) :-
	setof( S, inherits(X, purpose, S), Supers),
	member( Super, Supers ),
	purpose( Super, V ).

If one was dealing with a cyclic inheritance "hierarchy" then
the 'inherits' predicate would have to be augmented so it never
processed the same node twice, eg. by maintaining a list of the
nodes already visited.  Also, the "setof" solution may be inefficient
on large hierarchies, but that's beside the point...

The notion of "more specialized superclass" doesn't strike me as
being well-defined declaratively, unless one wants to say that
a node has an ordered list of parents or something.  Again, my
question is not so much whether one can code such a thing up in
Prolog (which one certainly can do without using recordz), but
how one might build an OOPS facility in Prolog that is reasonably
consistent with the declarative style of good Prolog programming.
I don't think that slot-filler style fits this requirement, for
example.

Any comments?

Mark Johnson

johnson@csli.stanford.edu
markj@cogito.mit.edu
*/

/*  A toy object-oriented system, modified as per Gandalf's suggestion */

:- ensure_loaded(library(basics)).
:- ensure_loaded(library(not)).

:- no_style_check(discontiguous).

:- op( 100, xfx, is_a ).
:- op( 100, xfx, doesnt_inherit ).

/*  object's definitions */

truck is_a object.
toy is_a object.

toytruck is_a toy.
toytruck is_a truck.

tt is_a toytruck.
 
purpose(object, nil).
purpose(truck, transport).

/*  inherits(Obj,Prop,Super) iff Obj inherits Prop from Super. */
/*     as i previous version                                  */

inherits(Obj, _, Obj).	% All objects inherit from themselves.
inherits(Obj, Prop, Super ) :-
	not Obj doesnt_inherit Prop,
	is_a( Obj, Parent),
	inherits( Parent, Prop, Super ).

find_purpose(X,V) :-	% modified in response to Gandalf's suggestion
	setof( S, inherits(X, purpose, S), Supers),
	member( Super, Supers ),
	purpose( Super, V ).