Newsgroups: comp.lang.prolog,comp.lang.misc
Path: cantaloupe.srv.cs.cmu.edu!das-news2.harvard.edu!oitnews.harvard.edu!newsfeed.rice.edu!bcm.tmc.edu!news.msfc.nasa.gov!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: Mercury suggestion for better multi-mode goals
Message-ID: <9525104.7911@mulga.cs.mu.OZ.AU>
Sender: news@cs.mu.OZ.AU (CS-Usenet)
Organization: Computer Science, University of Melbourne, Australia
References: <426pc4$fr9@otis.netspace.net.au>
Date: Thu, 7 Sep 1995 18:47:40 GMT
Lines: 88
Xref: glinda.oz.cs.cmu.edu comp.lang.prolog:13827 comp.lang.misc:23003

reiter@tornado (Peter Moulder) writes:

>I quite like the Mercury language so far.  

I'm glad to hear it.

>One thing I did notice though: the flow information (in, out) gives a 
>distinctive procedural (as opposed to purer logic) feel to using the language.

Mercury's explicit mode declarations do mean that the programmer must
think about the modes.  However, if you are writing a logic program
(not just a specification), and you do not want the program to go into
an infinite loop, it usually is necessary to think about the modes.
Without knowing the modes you generally cannot ascertain whether or not
a program will terminate.

Note that the situation is actually worse in Prolog than in Mercury, IMHO.
In Prolog, even though there are no explicit mode declarations,
you still need to think about the modes, because most Prolog
builtins and most Prolog user-defined predicates will only work in certain
modes.  Even worse, the potential result of calling a predicate in the
wrong mode is not limited to inefficiency or non-termination - in many
situations, you will instead get an incorrect result.
Since there are no explicit mode declarations, you need to rely on
documentation to tell you about the modes of predicates, but this
documentation is often missing and even when it is present, it is not
necessarily correct.

Furthermore, in Prolog you have to worry not just about the modes
but also about the order of execution; in Mercury, you don't have to
worry about the order of execution so much, since the compiler will
if necessary reorder goals based on the modes.  (Coroutining in Prologs
such as NU-Prolog and SICStus Prolog could help with this, but
in practice it doesn't help much, since coroutining is not the default,
and most of the library does not use it.)

The ideal of declarative logic programming would be a system in which
you could write a specification in logic and then have the system
automatically transform that specification into an efficient algorithm,
and compile the algorithm into efficient code.

>I started playing about with multi-moded goals.  
>One of the first things I noticed was that the if construct becomes useless;

Yes, the use of if-then-else does place constraints on the modes that
usually prevent a goal from being reversible.  (Note that this same
problem applies in Prolog too, not just in Mercury.)

>for example, you can't write
>  A < 3 ->
>    B = 1
>  ;
>    isplus(B, A, 2) 	% Multimoded version of  B is A + 2
>if one of the modes says that A is free (mode 'out') while B is bound ('in').
>The alternative is to use a disjuction:
>  (
>    A < 3,
>    B = 1
>  ;
>    not(A < 3),  	% A >= 3 if you like
>    isplus(B, A, 2)
>  )

I don't quite understand this example.
Isn't the alternative going to be ill-moded too?
Doesn't the first disjunct require `A' to be input to this goal?

>The problem with this is that it becomes nondeterministic.
>May I suggest that (goal, ... ; not(goal), ...) be recognised as a 
>deterministic construct?
>
>(I'm aware that a workaround is to declare a new goal, but my request stands.)

We have thought about this potential problem in the past, and discussed
both your suggestion and an alternative of automatically transforming
if-then-elses into the expanded (A, B ; \+ A, C) form if and when the
modes made it necessary to do so.  However, both of these approaches
could have a potentially bad impact on compilation time, and we have
not yet had much need for them.

I would be a lot more convinced that this was a real problem if I saw
some examples of real code where this caused trouble.

-- 
Fergus Henderson             |  #define x t=a[i],a[i]=a[m],a[m]=t
                             |  char a[]=" 12345678";main(m,i,j,t){for(i=m;i<
fjh@cs.mu.oz.au              |  9;x,i++)for(x,j=m;--j?(t=a[m-j]-a[m])-j&&t+j:
http://www.cs.mu.oz.au/~fjh  |  main(m+1)*0;);m-9||puts(a+1);} /* 8 queens */
