[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: if

From: Fergus Henderson
Subject: Re: if
Date: Thu, 1 Feb 2001 02:40:10 +1100

On 31-Jan-2001, Ron Stodden <address@hidden> wrote:
> Calum Grant wrote:
> > 
> > A simpler variant of this problem is
> > 
> >         insert_set(H, L, L) :- member(H, L), !.  % A "hack" according to FH
> >         insert_set(H, L, [H|L]).
> > 
> > which takes an item H and inserts it into a list L without duplicates, like
> > a simple set.  The second clause should only be applied if the first one
> > fails.  Therefore the ! is necessary.  This can be rewritten as
> > 
> >         insert_set(H, S0, S) :-
> >         (
> >                 member(H, S0) -> S0=S;  % A "hack" according to RS
> >                 S = [H|S0]
> >         ).
> > 
> > The difference is purely cosmetic, and I don't think it's worth arguing
> > about.  It's a bit like saying that "|" is better than ";".
> Argue?   Yes.   I would argue that the first is ultimately simpler,
> more 'elegant', immediately lucid, and I suspect generates less code
> and on that basis should run faster.  (Note the "should" <g>).

If-then-else is easier to understand, since it can be given
a declarative semantics that doesn't change depending on what
mode the predicate is called in.  Of course Prolog's if-then-else
isn't sound w.r.t. this declarative semantics... but other logic
languages like Goedel, NU-Prolog, and Mercury do better.

Your comments about efficiency are unlikely to be true for
optimizing implementations.  If-then-else is in fact much
easier to inline than cut.

Earlier Ron Stodden wrote

 | No, it is the if-then-else that is the hack.  It isn't necessary, and
 | in fact the biggest problem with users of languages that support
 | if-then-else is a failure to properly think through the combinations
 | of else paths since the language is no help (in coping with multiple
 | levels of interacting negations and those deMoivre theorems that trip
 | up procedural programmers all the time).  Getting these else paths
 | right is a far bigger job than getting the true path correct which is
 | by comparison usually simple and straighforward.

How does writing

         insert_set(H, L, L) :- member(H, L), !.
         insert_set(H, L, [H|L]).

make the "else" path easier to understand?
In this example, the logic of the else path is actually wrong,
if you treat it in isolation.  Consider what would happen if
you changed the order of the clauses!

If you wrote it as

         insert_set(H, L, L) :- member(H, L), !.
         insert_set(H, L, [H|L]) :- \+ member(H, L).

or even as

         insert_set(H, L, L) :- member(H, L), !.
         insert_set(H, L, [H|L])/* :- \+ member(H, L) */.

then I might agree with you, but advocates of cut over if-then-else
never do that, in my experience.  Of course writing things this way
requires making explicit all of those implicit negations.
You complain that if-then-else gives you no help with the else
paths, but it seems to me that using cut is worse, since with cuts
like these, the natural declarative reading of the following clause
becomes a lie.  If-then-else makes it clearer that the semantics of
the "else" path must include the negation of the condition.

Fergus Henderson <address@hidden>  |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: <>  |     -- the last words of T. S. Garp.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]