pat@alberta.UUCP (Patrick Fitzsimmons) (01/26/88)
If so, then I need your help. I am a new Turbo Prolog user having great difficultly trying to implement a prolog program in Turbo Prolog. The program works fine in other prologs. My problem is in the DOMAINS sections trying to get it to accept what I put. I thought that a more experienced user may be able to offer some help. Don't ask why I am using Turbo Prolog, I really don't want to but I must. To expand on my problem a bit, I currently have in the DOMAINS section: entry = symbol ; n(entry) list = entry* The n(entry) is meant to represent NOT entry. I have a negate predicate defined as: negate(n(G), G) :- ne(n(_), G). negate(G, n(G)) :- ne(n(_), G). ne(X, Y) :- not(X = Y). P.S. Sorry if I have posted this to an inappropriate newsgroup. Please send responses my e-mail and I will summarize in comp.lang.prolog if there is enough interest. |------------------------------------------------------------------------| | Patrick Fitzsimmons | pat@alberta.UUCP | | Computing Science Department | | | University of Alberta | | | Edmonton, Alberta | | | T6G 2H1 | | |------------------------------------------------------------------------|
ok@quintus.UUCP (Richard A. O'Keefe) (01/31/88)
In article <282@cavell.UUCP>, pat@alberta.UUCP (Patrick Fitzsimmons) writes: > > Don't ask why I am using Turbo Prolog, I really don't want to but I > must. To expand on my problem a bit, I currently have in the DOMAINS > section: > [Why "must"? Considering the value of your time, it would be cheaper for you or your employer or whoever is responsible for the "must" to buy a copy of ALS Prolog and let you get on with it.] > entry = symbol ; > n(entry) > list = entry* > > The n(entry) is meant to represent NOT entry. > This is a bad data structure design in ANY Prolog. I haven't a Turbo Prolog manual, but I suggest that you check yours very carefully: you can probably use ";" only in the form newdom = f1(t11,...,t1n) ; ... ; fm(tm1,...,tmn) where each case introduces a functor. None of the Turbo Prolog books I've checked has any examples resembling yours. (Mind you, each Turbo Prolog book I look at is worse than the last.) The rule for designing data structures in ANY Prolog is this: (1) list all the different situations (cases) you want to represent. Here you have formula-which-is-asserted formula-which-is-denied (2) For each case, identify the associated data. Here you have for a formula-which-is-asserted: the formula for a formula-which-is-denied: the formula (3) Make up a functor name for each situation. The associated data will be the arguments of the functor. Here you have p(F) {Positive assertion of formula F} n(F) {Negative assertion of formula F} (4) If your Prolog system supports types, write down the types. In Dec-10 Prolog (using the polymorphic type checker): :- type demo(F) --> p(F) | n(F). :- pred negate(demo(F), demo(F)). In Turbo Prolog: domains formula = /* something or other */ entry = p(formula) ; n(formula) predicates negate(entry, entry) You may be gritting your teeth and saying "that's a counsel of perfection, *I* have to worry about *efficiency*." I don't know about Turbo Prolog, but in most real Prolog implementations negate(p(F), n(F)). /* This is cleaner and */ negate(n(F), p(F)). /* is usually faster! */ will be *considerably* more efficient than the defaulty version. {Note that a characteristic of good data structure design is that you do *not* rely on negation!} > I have a negate predicate defined as: > > negate(n(G), G) :- > ne(n(_), G). > negate(G, n(G)) :- > ne(n(_), G). > ne(X, Y) :- > not(X = Y). > Note that (=)/2 in Turbo Prolog is not the same as (=)/2 in other Prologs. To start with, when applied to operands of numeric type, it is more like (=:=)/2 or is/2. No doubt there are enough people out there to correct me if I am wrong, but it is my understanding that Turbo Prolog does not permit partly instantiated data structures. So I do not think that the calls to ne/2 in your negate/2 are legal. Something like negate(n(G), G) :- not_n(G). negate(G, n(G)) :- not_n(G). not_n(n(_)) :- !, fail. not_n(_). might be more appropriate. On the other hand, this is pretty shocking too. You would be *much* better off going with the disciplined version. I have sent this reply to comp.lang.prolog for two reasons: -- I've had too much strife with the "reply" command getting confused with its addresses. -- I think the question of data structure design is important for everyone, whatever Prolog they are using. The method you chose is an obvious natural method which leads to endless trouble: you find you need cuts all over the place. The disciplined version leads to code which is both cleaner and faster, and when you are used to this approach it is easier too.