[net.lang.prolog] Compiler bug with + ? Nope.

ok@edai.UUCP (Richard O'Keefe) (09/02/83)

The Dec-10 Prolog compiler does NOTHING to \+ .
If you have \+ member(X,L) in your program (\+ is an operator,
the only time you need parentheses after it is when the negated
goal is a conjunction or disjunction), this is handled just like
mrs_mc_gurgle(member(X,L)) where
	mrs_mc_gurgle(X) :- call(X), !, fail.
	mrs_mc_gurgle(X).
{This isn't a sexist invented name.  Fans of Beachcomber will recognise it.}

The fact that the compiler doesn't look inside \+ often causes problems
when the negated goal calls a compiled predicate that you forgot to
declare public.  \+ X *always* hands X over to the interpreter for
execution, and if that goal wasn't declared public the interpreter
won't know about it.  member/2 is of course declared public in the
utility file that defines it.  I'm not sure off-hand, but I think there
is no compiled definition of \+, so the whole \+member(X,L) goal is
being handed off to the interpreter in this case.  Negation is thus
necessarily slower in compiled code than in interpreted code, not
proportionally, but absolutely.  (Negation is pretty dubious anyway.)

The figure reported for compiled \+member(X,L) is astonishingly high,
but it is impossible to explain/check/believe it without seeing the
entire test program.  For example, one thing that might explain it
would be if the call were compiled, but member were interpreted, and
without seeing the whole program I can't rule that explanation out.

     There is no fundamental reason why a Prolog compiler *couldn't*
compile \+ _ and (_ -> _ ; _) in-line.  In fact I have just completed
a design extension for Prolog-X to do just that.  The Dec-10 compiler
handles only the following control structures: repeat, fail, !, ',',
and ';'.

     Not compiling \+ in-line has the consequence that the variables
X and L in \+ member(X,L) are classified as global rather than local,
which may increase the rate at which garbage collections are done. 
All in all, one should expect \+member(X,L) in compiled code to be
markedly slower than non_member(X,L) where
	non_member(X, []).
	non_member(X, [H|T]) :- X \== H, non_member(X, T).
Note that the predicate \= in Dec-10 Prolog is just another utility,
\== is a genuine primitive.