[comp.lang.prolog] Do you consider yourself a TURBO PROLOG expert?

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.