From: Jeff Dalton
Subject: Re: Processing deleted elements of a list
Date: 
Message-ID: <5470@skye.ed.ac.uk>
In article <······················@m.cs.uiuc.edu> ·······@cs.uiuc.edu (Alan M. Carroll) writes:

>I got a lot of email also, and the concensus (which I've already
>implemented) is basically
>
>    (delete-if #'(lambda (x) (and (funcall PRED x) (progn (PROCESS x) t))))
>

That's fine, except that you shouldn't use AND that way.
You're not trying to see if two things are true but do
two things if a predicate is true: 1. process; 2. indicate
that the predicate returned true. 

  (delete-if #'(lambda (x) (if (funcall pred x) (progn (process x) t))) ...)

or even

  (delete-if #'(lambda (x)
                 (let ((result (funcall pred x)))
                   (when result (process x))
                   result))
             ...)

From: Alan M. Carroll
Subject: Re: Processing deleted elements of a list
Date: 
Message-ID: <1991Oct25.194756.25102@m.cs.uiuc.edu>
In article <····@skye.ed.ac.uk>, ····@aiai.ed.ac.uk (Jeff Dalton) writes:
> In article <······················@m.cs.uiuc.edu> ·······@cs.uiuc.edu (Alan M. Carroll) writes:
> >    (delete-if #'(lambda (x) (and (funcall PRED x) (progn (PROCESS x) t))))
> That's fine, except that you shouldn't use AND that way.
> You're not trying to see if two things are true but do
> two things if a predicate is true: 1. process; 2. indicate
> that the predicate returned true. 
>   (delete-if #'(lambda (x) (if (funcall pred x) (progn (process x) t))) ...)

I disagree. The use of (and) is justified because the logical value of
the expression matters. It is not my personal style to depend on the
fact that (if) defaults to nil if the predicate is false and the else
clause is missing. IMHO the use of (and) makes it clearer that the
return value matters. Even CLtL is ambivalent about this point.

-- 
Alan M. Carroll          <-- Another casualty of applied metaphysics
Epoch Development Team   
Urbana Il.               "I hate shopping with the reality-impaired" - Susan
From: Jeff Dalton
Subject: Re: Processing deleted elements of a list
Date: 
Message-ID: <5533@skye.ed.ac.uk>
In article <······················@m.cs.uiuc.edu> ·······@cs.uiuc.edu (Alan M. Carroll) writes:
>In article <····@skye.ed.ac.uk>, ····@aiai.ed.ac.uk (Jeff Dalton) writes:
>> In article <······················@m.cs.uiuc.edu> ·······@cs.uiuc.edu (Alan M. Carroll) writes:
>> >    (delete-if #'(lambda (x) (and (funcall PRED x) (progn (PROCESS x) t))))
>> That's fine, except that you shouldn't use AND that way.
>> You're not trying to see if two things are true but do
>> two things if a predicate is true: 1. process; 2. indicate
>> that the predicate returned true. 
>>   (delete-if #'(lambda (x) (if (funcall pred x) (progn (process x) t))) ...)
>
>I disagree. The use of (and) is justified because the logical value of
>the expression matters. It is not my personal style to depend on the
>fact that (if) defaults to nil if the predicate is false and the else
>clause is missing. IMHO the use of (and) makes it clearer that the
>return value matters. Even CLtL is ambivalent about this point.

I stand by my claim about AND, though I'd probably weaken it somewhat.
I was wrong not to put an else-form of NIL in the IF.

I think you are right that the logical value is important.
However, (IF expr T NIL) is not a bad way to return a boolean.

The reason I don't like the use of AND above is as follows.

The expression (and (funcall PRED x) (progn (PROCESS x) t)) is
using AND to return a logical value but also for sequential
evaluation.  However (PROCESS x) isn't being used for it's
logical value, and so the (progn t) is needed to patch things
up.

When AND is used for sequential/conditional evaluation, I think
there's a difference between things like

[1] (AND (NUMBERP X) (> X 0))

which relies on AND performing conditional evaluation, and
constructions like 

[2] (AND (pred x) (process x))

which looks like it ought to be an IF.  Nor am I the only one who
thinks this (or has thought it).  See, eg, the style note on AND in
Saturday Evening Edition Revised MacLisp Manual, page 29, where's
there's an example (AND X (PRINT X)).

Still worse are cases where it looks like AND is being used instead
of PROGN.  For example:

[3] (and (pred x) (progn (process x) t) ...)

The example we're considering is:

[4] (and (funcall PRED x) (progn (PROCESS x) t))

This is very close to be an instance of both [2] and [3].
Consequently, I think it is clearer to use IF rather than AND,
thus:

   (if (funcall pred x) (progn (process x) t) nil)

Whenever I see something like (PROGN (DO-SOMETHING) T), where the T is to
satisfy some logical form containing the PROGN, I think "there ought
to be an abstraction that makes that unnecessary".  In this case Common
Lisp doesn't supply anything that fits the bill and, since I'm not
sure what the new abstration should be, I don't want to write a macro.
So on balance, I think IF is the best choice.

-- jd