Newsgroups: comp.lang.prolog
Path: cantaloupe.srv.cs.cmu.edu!rochester!udel!gatech!howland.reston.ans.net!newsfeed.internetmci.com!news.mel.aone.net.au!inferno.mpx.com.au!news.unimelb.EDU.AU!cs.mu.OZ.AU!munta.cs.mu.OZ.AU!fjh
From: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Subject: Re: Question on strange behavior
Message-ID: <9523923.5634@mulga.cs.mu.OZ.AU>
Sender: news@cs.mu.OZ.AU (CS-Usenet)
Organization: Computer Science, University of Melbourne, Australia
References: <4164k5$f8d@gap.cco.caltech.edu>
Date: Sun, 27 Aug 1995 13:05:22 GMT
Lines: 74

cilibrar@gluttony.ugcs.caltech.edu (Rudi Cilibrasi) writes:

>I've just started learning Prolog.  It seems a very interesting language,
>but there is one part I just don't understand.  Given the following
>program:
>
>rsucc(zero,one).
>rsucc(one,two).
>rsucc(two,three).
>rsucc(three,four).
>rsucc(four,five).
>rsucc(five,six).
>rsucc(six,seven).
>rsucc(seven,eight).
>rsucc(eight,nine).
> 
>rplus(A,B,Result) :-
>        A = zero,
>        B = Result.
>rplus(A,B,Result) :-
>        A \= zero,
>        rsucc(Adown, A),
>        rsucc(Resultdown, Result),
>        rplus(Adown,B,Resultdown).
>
>I submit the following queries:
[...]
>4 ?- rplus(X,three,five).
>
>No

The problem here is your use of Prolog's non-logical inequality
operator `\='.

Prolog tries the first clause first, but that fails, since three is
not equal to five.  Then Prolog tries the second clause.  It
executes the goal `A \= zero', where `A' is bound to the free
variable `X'.  The way `\=' works is to attempt to unify its
two arguments, and if they can unify - as they can in this case - it fails.
In the case where the arguments to `\=' are free variables, this is unsound.
(E.g. in your program, there are certainly many values of `A' for which
`A' is not equal to zero,)  Nevertheless, that's how Prolog works.

You can fix the program by changing the order of the conjuncts
in the second clause of `rplus':

	rplus(A,B,Result) :-
		rsucc(Adown, A),
		A \= zero,
		rsucc(Resultdown, Result),
		rplus(Adown,B,Resultdown).

This guarantees that `A' will be ground (by the call to `rsucc')
before you call `\='.

Note that if you had used a purely logical language like Mercury
(which is completely pure) or Geodel (which is pure except for I/O),
this problem would not have arisen.  In Goedel, the equivalent
to Prolog's `\=' is spelt `~='.  If the arguments to `~=' are not
ground, the call will "delay"; Goedel will continue to execute other
goals until the arguments to `~=' do become ground, at which point
the call to `~=' will be "woken up" and Goedel will execute it.
In Mercury, `\=' is spelt the same way as in Prolog, but it has
a sound semantics.  The Mercury compiler would automatically reorder the
conjuncts in the second clause of `rplus' so that they were executed
in the order shown above.  (The difference here between Goedel
and Mercury is that in Goedel reordering is done at runtime, whereas
in Mercury it is done at compile time.)

-- 
Fergus Henderson              | Designing grand concepts is fun;
fjh@cs.mu.oz.au               | finding nitty little bugs is just work.
http://www.cs.mu.oz.au/~fjh   | -- Brooks, in "The Mythical Man-Month".
PGP key fingerprint: 00 D7 A2 27 65 09 B6 AC  8B 3E 0F 01 E7 5D C4 3F
