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 ).