Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

COMPLEMENT and -IF-NOT functions

52 views
Skip to first unread message

Erik Naggum

unread,
Jan 25, 1998, 3:00:00 AM1/25/98
to

although DELETE-IF-NOT and friends are deprecated, I find myself using
them quite often and not really finding a much better replacement. what
do people do when you want to delete an element that does not satisfy a
particular predicate? is COMPLEMENT your choice?

these are the ways that I have thought of to delete an element that fails
to satisfy <predicate> from <list>:

(delete-if (complement <predicate>) <list>)

although this was intended as the preferred replacement, it neither looks
right to me nor performs right, not the least of which is because it
throws away any knowledge I or the system might have about the function
being complemented. it seems to be extremely hard to make this function
yield a reasonably fast function as a result. when defined as

(defun complement (function)
(lambda (&rest arguments)
(declare (dynamic-extent arguments))
(not (apply function arguments))))

it should have been possible for this function to call directly to the
closed-over function without changing its own arguments or restifying
them, but to my (somewhat limited) knowledge, no Lisp compiler does that.
CMUCL, known to be good at suggesting where it could need a declaration,
complains about the lack of a type declaration so it cannot inline the
COMPLEMENT function if it does not know the number of arguments, but
supplying that doesn't help. on average, using COMPLEMENT costs as much
or more than the predicate I wish to negate.

(delete-if #'not <list> :key <predicate>)

with this form, I have saved myself a lot of execution time relative to
the COMPLEMENT case, but this feels even more wrong than COMPLEMENT does,
so I include it only because I twisted my brain and this came out.

(delete-if (lambda (item) (not (<predicate> item))) <list>)

now we're getting somewhere, at least in terms of execution time. this
also "feels" better than COMPLEMENT in that my knowledge of the function
whose complement I'm asking for is retained.

(defun not-<predicate> (item) (not (<predicate> item)))
(delete-if #'not-<predicate> <list>)

in many cases, it makes sense to define an apparent negative of some
existing predicate with some useful name that is not just NOT-<WHATEVER>,
and the opportunity to design things better can thus be appreciated.
whenever this option is available, the deprecation of DELETE-IF-NOT is
either moot or makes it easier to exercise this option.

finally, another option is to rename REMOVE-IF-NOT to EXTRACT-IF and
DELETE-IF-NOT to KEEP-IF or somesuch and perhaps invent useful names of
the other -IF-NOT functions, but this seems somewhat dubious. however,
it could be defended by assessing current practice.

I'm dissatisfied with all the options, really. while it has merit,
-IF-NOT is also not an _obviously_ great idea. the messy situation with
both :TEST and :TEST-NOT is certainly a prime candidate for cleanup.
COMPLEMENT goes halfway towards a better world, but as of now, it has too
high costs and too few benefits to be worth bothering with in my view.

so, would anything make me happier about COMPLEMENT? it would have
helped a lot if the returned function had a recognizable wrapper that
told the caller it should invert a test. this would be a fundamental
change to some parts of the Common Lisp system in that we have no such
properties of functions at present.

however, one conceptually simple way to obtain this would be if the
FUNCTION class could have a subclass PREDICATE which meant that using the
value always turned it magically into NIL or T. any function instance
could be coerced to a predicate by a declaration or a (special) operator
PREDICATE which would affect the calling semantics. properly recognized
by the called function, this could be used to refrain from returning
multiple values and other useful performance improvements. (while we're
at it, this could make a function return either NIL or T instead of the
generalized boolean if it were being used as a predicate in a situation
where the returned value might linger and inhibit garbage collection.)
with this in place, a subclass COMPLEMENT-PREDICATE of PREDICATE could
mean that using the value always turned it magically into T or NIL where
PREDICATE would return NIL or T, respectively. (both PREDICATE and
COMPLEMENT-PREDICATE would be system classes, of course.)

this may sound like a lot of work to help realize the deprecation of the
-IF-NOT functions and the :TEST-NOT arguments, and it may just be too
costly, but it appears to me that if something like COMPLEMENT is to
succeed for real, it needs more than a hand-waving over the performance
issues involved. (I imagine that performance and some form of language
elegance went into the original -IF-NOT and :TEST-NOT design to begin
with. it appears that some of this rationale got lost in the translation
to COMPLEMENT.) to support COMPLEMENT fully already requires extensive
and depressingly unique optimizations in the compiler. with a subclass
of FUNCTION that enforced the knowledge that it was being used as a
predicate, numerous optimizations are suddenly available. also, as long
as the value is used as a predicate, there would be no difference apart
from performance gains over using the old function call semantics, if we
assume that the necessary testing for whether a function is called with
known predicate behavior or regular value-returning semantics is "free".
this means that this work has no impact on the behavior of existing code,
but adds a sizable opportunity for both conceptual and performance
improvements if supported and implemented.

finally, it is my understanding that by "deprecating" a language feature,
the intent is to remove it at a later stage, but if there is an unclear
need for such a feature, it will forever be "deprecated" yet remain in
the language, and thus work against its stated goals. therefore, I think
we have an obligation to either support the deprecating with much better
ways to solve the same problem, or work to revoke the deprecated status.

I look forward to your comments.

#:Erik
--
The year "98" was new 1900 years ago. | Help fight MULE in GNU Emacs 20!
Be year 2000 compliant, write "1998"! | http://sourcery.naggum.no/emacs/

Pierpaolo Bernardi

unread,
Jan 26, 1998, 3:00:00 AM1/26/98
to

Erik Naggum (cle...@naggum.no) wrote:
: although DELETE-IF-NOT and friends are deprecated, I find myself using

: them quite often and not really finding a much better replacement. what
: do people do when you want to delete an element that does not satisfy a
: particular predicate? is COMPLEMENT your choice?

: these are the ways that I have thought of to delete an element that fails
: to satisfy <predicate> from <list>:

: (delete-if (complement <predicate>) <list>)

: although this was intended as the preferred replacement, it neither looks
: right to me nor performs right, not the least of which is because it
: throws away any knowledge I or the system might have about the function
: being complemented. it seems to be extremely hard to make this function
: yield a reasonably fast function as a result. when defined as

: (defun complement (function)
: (lambda (&rest arguments)
: (declare (dynamic-extent arguments))
: (not (apply function arguments))))

I don't think that the dynamic-extent declaration is appropriate in
this place. What if FUNCTION stores its arglist somewhere?
e.g. for caching.

A useful technique for making complement fast, is to use
compiler-macros for the functions which are likely to use complement.

Pierpaolo.

Michael Greenwald

unread,
Jan 26, 1998, 3:00:00 AM1/26/98
to

bern...@cli.di.unipi.it (Pierpaolo Bernardi) writes:

>Erik Naggum (cle...@naggum.no) wrote:

>: (defun complement (function)


>: (lambda (&rest arguments)
>: (declare (dynamic-extent arguments))
>: (not (apply function arguments))))

>I don't think that the dynamic-extent declaration is appropriate in


>this place. What if FUNCTION stores its arglist somewhere?
>e.g. for caching.

It's approppriate. APPLY spreads ARGUMENTS. If FUNCTION stores *its*
arguments, that would be a *different* list. (If you *do* want to
cache the arguments of a predicate, introdicuing side-effects into
something which is best defined as side-effect free, then it's a good
idea to do the copying before storing, putting the burden where it
belongs, rather than on all callers).

I don't know the legality of the "optimization" (?) of somehow using a
single stack-consed &rest list for two (dynamically) nested functions
that are both &rest arguments, and the outer one has dynamic-extent
declared. This strikes me as questionable at best.

Pierpaolo Bernardi

unread,
Jan 26, 1998, 3:00:00 AM1/26/98
to

Michael Greenwald (mich...@Xenon.Stanford.EDU) wrote:
: bern...@cli.di.unipi.it (Pierpaolo Bernardi) writes:

: >Erik Naggum (cle...@naggum.no) wrote:

: >: (defun complement (function)


: >: (lambda (&rest arguments)
: >: (declare (dynamic-extent arguments))
: >: (not (apply function arguments))))

: >I don't think that the dynamic-extent declaration is appropriate in


: >this place. What if FUNCTION stores its arglist somewhere?
: >e.g. for caching.

: It's approppriate. APPLY spreads ARGUMENTS. If FUNCTION stores *its*
: arguments, that would be a *different* list.

No. Check the FM.

: (If you *do* want to


: cache the arguments of a predicate, introdicuing side-effects into
: something which is best defined as side-effect free, then it's a good
: idea to do the copying before storing, putting the burden where it
: belongs, rather than on all callers).

That is a different issue.

: I don't know the legality of the "optimization" (?) of somehow using a


: single stack-consed &rest list for two (dynamically) nested functions
: that are both &rest arguments, and the outer one has dynamic-extent
: declared. This strikes me as questionable at best.

Check the FM.

Pierpaolo.

Erik Naggum

unread,
Jan 26, 1998, 3:00:00 AM1/26/98
to

* Pierpaolo Bernardi
| No. Check the FM.

I love those CLPFH responses.

"yes", says ANSI X3.226-1994, at the very bottom of page 3-73.

#:Erik, LLLD

Erik Naggum

unread,
Jan 26, 1998, 3:00:00 AM1/26/98
to

* Sam Steingold <s...@usa.net>
| >>>> In a very interesting message <30948291...@naggum.no>
| >>>> Sent on 26 Jan 1998 18:45:40 +0000
| >>>> Honorable Erik Naggum <cle...@naggum.no> writes
| >>>> on the subject of "Re: COMPLEMENT and -IF-NOT functions":

| >> * Pierpaolo Bernardi
| >> | No. Check the FM.
| >>
| >> I love those CLPFH responses.
| >>
| >> "yes", says ANSI X3.226-1994, at the very bottom of page 3-73.
| >>
| >> #:Erik, LLLD
|
| For the benefit of the uninitiated, could you please expand the
| abbreviations? (llld, fm, clpfh etc. I know what ANSI X3.226-1994 is).

I guess FM is the F*cking Manual (which I think is somewhat ambiguous
when it stands alone, like, do sex therapists from Hell ask you to go
read it if they get tired of helping you?)

*FH is slang from the BOFH hierarchy, and means From Hell. I just made
the Common Lisp Programmer version up on the spot.

LLD is the abbreviation for the degree of Legum Doctor, or doctor of
laws, not uncommon to lawyers. the first L could stand for "language".
cudos for "honorable", it is just right in the context. :)

Pierpaolo Bernardi

unread,
Jan 27, 1998, 3:00:00 AM1/27/98
to

Erik Naggum (cle...@naggum.no) wrote:
: * Pierpaolo Bernardi
: | No. Check the FM.

: I love those CLPFH responses.

: "yes", says ANSI X3.226-1994, at the very bottom of page 3-73.

What is ANSI X3.226-1994? If it is the ANSI Common Lisp spec, could
you be so kind to give the Hyperspec reference? I don't have a
printed copy.

Thank you.

Pierpaolo.


: #:Erik, LLLD
: --

Erik Naggum

unread,
Jan 27, 1998, 3:00:00 AM1/27/98
to

* Pierpaolo Bernardi

| What is ANSI X3.226-1994? If it is the ANSI Common Lisp spec, could you
| be so kind to give the Hyperspec reference? I don't have a printed copy.

are you kidding me? "check the FM", you say, and then _you_ request a
reference that you can actually use? gimme a break!

please provide a suitable reference to the "FM" you think supports your
position ("no"), and then we can start talking.

#:Erik
--
I believe in life after Year 2000, four-digit years, and 24-hour clocks. I
believe in ISO 8601 as the only external time representation. I believe in
a monotonically increasing number of milliseconds as the only internal time
representation. I pledge to fight time zones and other time formats. Amen

Pierpaolo Bernardi

unread,
Jan 28, 1998, 3:00:00 AM1/28/98
to

Michael Greenwald (mich...@Xenon.Stanford.EDU) wrote:

bern...@cli.di.unipi.it (Pierpaolo Bernardi) writes:

>Michael Greenwald (mich...@Xenon.Stanford.EDU) wrote:

>: It's approppriate. APPLY spreads ARGUMENTS. If FUNCTION stores *its*
>: arguments, that would be a *different* list.

>No. Check the FM.

FM? As in RTFM? (I hadn't seen FM alone before).

The Fantastic Manual.
(http://www.harlequin.com/education/books/HyperSpec/FrontMatter/)

BTW, If I have been brief in my previous reply, it is because I posted
it at 18:49 (local time), and at 18:55 they reboot the machines, so I
was in hurry.

In any case, are you sure? It would be helpful if you could cite
something here.

It is what I infer from reading the APPLY and DYNAMIC-EXTENT sections,
and all the related issues writeups in the HyperSpec.

Certainly for all cases except fn's with &rest lists
calling other fn's with &rest lists (which I mentioned, separately
below), I'm pretty sure my statement is uncontroversial. Right?

I specifcially said "I don't know" about the legality in
in the case of COMPLEMENT calling F1, where F1 is:
(defun f1 (&rest args)
(setq *f1-cache* args))

Yes, that is the controversial case. I suggested you read the FM
yourself so you could know too. The relevant passage is in the APPLY
node:

Spec> When the function receives its arguments via &rest, it is permissible
Spec> (but not required) for the implementation to bind the rest parameter
Spec> to an object that shares structure with the last argument to apply.
Spec> Because a function can neither detect whether it was called via apply
Spec> nor whether (if so) the last argument to apply was a constant,
Spec> conforming programs must neither rely on the list structure of a rest
Spec> list to be freshly consed, nor modify that list structure.

My question is whether section 5.2.2 of CLtL still holds, or if it was
overridden in the ANSI spec.

CLtL didn't specified whether the &rest list is freshly consed or not.
The ANSI Standard (I mean the HyperSpec) specifies that this is
implementation dependent.

Clearly, the desired intent of CL is that &rest have indefinite
extent. CLtL2 re-allows the performance optimization that APPLY of a
function that has &rest args can share list structure with the caller.
There are two cases. (1) You can't depend on &rest args to be newly
consed in portable code, in which case the SETQ in F1 is not portable
(but Erik's dynamic-extent declaration is ok). Or, (2), you can
depend on &rest args to be newly consed (unless you declare
dynamic-extent) in which case the SETQ is legal, but so is Erik's
dynamic-extent declaration. Either way, the declaration is appropriate.

Why do you think that case (1) is ok? IMHO, it's not so (with the
reservation that I don't know what's at the very bottom of page 3-73).

You are mixing two issues: whether the rest lists can be modified or
not (they shouldn't), and whether they have dynamic extent or not.
These are two different, even if somewhat related, issues.

There's an alternative possibility, independent of which case we deal
with. Does the spec allow us to rely on indefinite extent, even
though we can't rely on freshly consed? Is *that* what you're trying
to point me to in some F-manual?

Yes. Exactly.

If it *is* specified (quite
possible: Kent, do you want to specify Original Framers Intent?), then
I still don't think it's perfectly clear. But that's the only
interpretation where the SETQ is legal, but the declaration isn't.

It's not so unclear. If you want to use the dynamic-extent
declaration on the &rest list, you must be sure that this list indeed
has a dynamic extent (duh). You cannot pass it to an unknown function
(via APPLY or otherwise), unless this function obeys some agreed upon
protocol which forbids the list to escape the dynamic extent. (With
the reservation of page 3-73 ...)

Now, the other issue you raised is that if this unknown function
has a &rest args and wants to modify it, then should make a copy.
No controversy on this.

>: I don't know the legality of the "optimization" (?) of somehow using a
>: single stack-consed &rest list for two (dynamically) nested functions
>: that are both &rest arguments, and the outer one has dynamic-extent
>: declared. This strikes me as questionable at best.

>Check the FM.

I don't have the ANSI spec available, so I *still* don't know the
legality of this. If you have it, I'd be grateful if you quoted
the relevant section. Thanks.

The FMน is available on line at the above mentioned URL, and can be
downloaded for local browsing. (Thanks to Kent Pitman & Harlequin).

All this, IMHO, FWIW, WKWIOTVBOP3-73.

Greetings,
Pierpaolo

น8-)


Pierpaolo Bernardi

unread,
Jan 28, 1998, 3:00:00 AM1/28/98
to

Erik Naggum (cle...@naggum.no) wrote:
: * Pierpaolo Bernardi

: | What is ANSI X3.226-1994? If it is the ANSI Common Lisp spec, could you
: | be so kind to give the Hyperspec reference? I don't have a printed copy.

: are you kidding me? "check the FM", you say, and then _you_ request a
: reference that you can actually use? gimme a break!

Why do you give references that people cannot use in the first place?


: please provide a suitable reference to the "FM" you think supports your


: position ("no"), and then we can start talking.

Sorry. I'm no interested in talking with you.

: #:Erik

Erik Naggum

unread,
Jan 28, 1998, 3:00:00 AM1/28/98
to

* Pierpaolo Bernardi

| Why do you give references that people cannot use in the first place?

that's the question that was on my mind when I replied to you, actually.

I regret that you didn't understand from my reply that "check the FM" is
useless, got somewhat embarrassed by your non-reference, and rushed to
fix it with a precise, useful reference. you see, it is amazing that
anybody can even have the _gall_ to say "check the FM" with respect to a
document this big, but you seem to continue to think it's perfectly OK
and that my _precise_ reference is _worse_ than your useless piece of
arrogant drivel. I find this moderately amusing.

the reference I provided _is_ useful to anybody who actually _has_ a copy
of the standard ("the FM"). I wanted to find out: (1) did you have a
copy, or where you just blowing hot air? (2) would you provide a useful
reference to your own "check the FM" uselessness, or would you get really
pissed because you were just blowing hot air and were exposed as such?

I conclude that you were just blowing hot air.

| Sorry. I'm no interested in talking with you.

my loss, I'm sure.

Barry Margolin

unread,
Jan 29, 1998, 3:00:00 AM1/29/98
to

In article <30949984...@naggum.no>, Erik Naggum <cle...@naggum.no> wrote:
> the reference I provided _is_ useful to anybody who actually _has_ a copy
> of the standard ("the FM"). I wanted to find out: (1) did you have a
> copy, or where you just blowing hot air? (2) would you provide a useful
> reference to your own "check the FM" uselessness, or would you get really
> pissed because you were just blowing hot air and were exposed as such?

Almost no one has a copy of the FS (F* Standard). I was on the ANSI
committee and *I* don't have a copy of it. When I want to grab something
off the bookshelf I use CLtL2 (I have a reasonably good memory for what
changed since it was published) and when I want something more complete I
use the HyperSpec.

However, while references to page numbers in the ANSI spec are pretty
useless, the HyperSpec includes the ANSI spec's chapter and section
numbers, so a reference to a section # in the ANSI spec can generally be
treated as a reference to the corresponding section of the HyperSpec.

--
Barry Margolin, bar...@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
Support the anti-spam movement; see <http://www.cauce.org/>
Please don't send technical questions directly to me, post them to newsgroups.

Erik Naggum

unread,
Jan 29, 1998, 3:00:00 AM1/29/98
to

* Barry Margolin

| Almost no one has a copy of the FS (F* Standard).

OK, so my attempted joke fell utterly on its face. the point was really
no more than to show that by using a silly abbreviation (nobody used "FM"
for "F*cking Manual" before Pierpaolo Bernardi did) while getting on his
high horse and engaging in hand-waving over the _entire_ standard, he
communicated arrogance and uselessness in an unfunny way. I tried to
communicate arrogance and uselessness in a funny way, while including a
Clinton clause with which I could show that I had given a very precise
reference, should that be needed, or really hadn't given a reference at
all, should that be needed. oh, well. sorry for wasting people's time.

however, to the issue at hand:

I believe there's a different issue at work than the one that appears to
be the focal point. Pierpaolo appears to believe that Common Lisp
requires functions to honor a contract that says "unless you _know_ what
will happen to a binding that you declare DYNAMIC-EXTENT, you cannot use
that declaration" _and_ that his contract has indefinite extent, as it
were: that any violation anywhere will render a program non-conforming
and that the behavior is therefore undefined. I contend that the latter
part of this is not only silly, it's counter-productive in the extreme
and renders DYNAMIC-EXTENT worthless, because it is _impossible_ to know
how any function uses its arguments unless it is part of that function's
contract (like the symbol name argument to INTERN, or the key to a hash
function, which is subect to a whole separate clause, 18.1.2).

whenever a function may destructively modify an argument, it has to say
so in its specification, and we may safely assume that unless such is
part of its specification, it does not destructively modify an argument.
likewise, when the exported behavior requires the caller to refrain from
destructively modifying an object passed as argument, that must be part
of the specification. however, there is no such requirement on functions
to document their _internal_ use of their arguments. if a function needs
an object passed as an argument to remain the same for the rest of its
lifetime (such as when memoizing) it can just _copy_ the object, in
preference to imposing a "don't touch this" rule on all its callers in
_violation_ of the contract. there are a few exceptions to this rule;
INTERN, in particularน.

in the context of COMPLEMENT, we are _clearly_ talking about predicates,
the exported behavior of which is _clearly_ side-effect-free, and their
contract _clearly_ precludes imposing a non-destructive policy on any of
the arguments they were passed.

finally, some quotes and references. as part of the description of
APPLY, we find:

When the function receives its arguments via &rest, it is permissible (but
not required) for the implementation to bind the rest parameter to an
object that shares structure with the last argument to apply. Because a
function can neither detect whether it was called via apply nor whether (if
so) the last argument to apply was a constant, conforming programs must
neither rely on the list structure of a rest list to be freshly consed, nor
modify that list structure.

as part of the description of DYNAMIC-EXTENT, we find:

In some containing form, F, this declaration asserts for each vari (which
need not be bound by F), and for each value vij that vari takes on, and for
each object xijk that is an otherwise inaccessible part of vij at any time
when vij becomes the value of vari, that just after the execution of F
terminates, xijk is either inaccessible (if F established a binding for
vari) or still an otherwise inaccessible part of the current value of vari
(if F did not establish a binding for vari). The same relation holds for
each fni, except that the bindings are in the function namespace.

The compiler is permitted to use this information in any way that is
appropriate to the implementation and that does not conflict with the
semantics of Common Lisp.

in the examples section of DYNAMIC-EXTENT, we find:

A variant of this is the so-called ``stack allocated rest list'' that can
be achieved (in implementations supporting the optimization) by:

(defun f (&rest x)
(declare (dynamic-extent x))
...)

Note that although the initial value of x is not explicit, the f function
is responsible for assembling the list x from the passed arguments, so the
f function can be optimized by the compiler to construct a stack-allocated
list instead of a heap-allocated list in implementations that support such.

in the discussion of the DYNAMIC-EXTENT issue, we find:

KMP: ... it still raises the question of whether we should define
per-function for every CL function whether any of the arguments is
permitted to be "saved" so that CL programs don't get any funny
surprises. If we don't, it ends up being implementor's discretion how to
resolve cases ... and everyone might not agree that all cases are
... obvious ...

<URL:http://www.harlequin.com/books/HyperSpec/Issues/iss142-writeup.html>

#:Erik
-------
น although interns appear to be no exception elsewhere

Pierpaolo Bernardi

unread,
Jan 30, 1998, 3:00:00 AM1/30/98
to

Erik Naggum (cle...@naggum.no) wrote:
: * Pierpaolo Bernardi

: | Why do you give references that people cannot use in the first place?

: that's the question that was on my mind when I replied to you, actually.

: I regret that you didn't understand from my reply that "check the FM" is
: useless, got somewhat embarrassed by your non-reference, and rushed to
: fix it with a precise, useful reference. you see, it is amazing that
: anybody can even have the _gall_ to say "check the FM" with respect to a
: document this big, but you seem to continue to think it's perfectly OK
: and that my _precise_ reference is _worse_ than your useless piece of
: arrogant drivel. I find this moderately amusing.

: the reference I provided _is_ useful to anybody who actually _has_ a copy


: of the standard ("the FM"). I wanted to find out: (1) did you have a
: copy, or where you just blowing hot air? (2) would you provide a useful
: reference to your own "check the FM" uselessness, or would you get really
: pissed because you were just blowing hot air and were exposed as such?

: I conclude that you were just blowing hot air.

I think the readers of comp.lang.lisp are intelligent enough to decide
for themselves who blows what.


: | Sorry. I'm no interested in talking with you.

: my loss, I'm sure.

See? why can agree on something.


Pierpaolo Bernardi

: #:Erik
: --

Pierpaolo Bernardi

unread,
Jan 30, 1998, 3:00:00 AM1/30/98
to

Erik Naggum (cle...@naggum.no) wrote:
: * Barry Margolin

: <URL:http://www.harlequin.com/books/HyperSpec/Issues/iss142-writeup.html>


CLHS: Function COMPLEMENT
--------------------------

...

Notes:

(complement x) == #'(lambda (&rest arguments) (not (apply x arguments)))


CLHS: 1.4.1.3 Special Symbols
------------------------------

...

==

This indicates code equivalence. For example:

(gcd x (gcd y z)) == (gcd (gcd x y) z)

This means that the results and observable side-effects of evaluating
the form (gcd x (gcd y z)) are always the same as the results and
observable side-effects of (gcd (gcd x y) z) for any x, y, and z.


Q.E.D.


Regards,
Pierpaolo Bernardi

: #:Erik

Kelly Murray

unread,
Jan 30, 1998, 3:00:00 AM1/30/98
to

> (complement x) == #'(lambda (&rest arguments) (not (apply x arguments)))

Does seem like much of a complement to disagree 100%,
but then again, someone else started it by giving it an argument.

<smile>

-Kelly Murray k...@franz.com
(btw, compliment was not spelled correctly)

Barry Margolin

unread,
Jan 30, 1998, 3:00:00 AM1/30/98
to

In article <6at2ig$c8p$2...@croci.unipi.it>,

Pierpaolo Bernardi <bern...@cli.di.unipi.it> wrote:
>CLHS: Function COMPLEMENT
>--------------------------
>
>...
>
>Notes:
>
> (complement x) == #'(lambda (&rest arguments) (not (apply x arguments)))

Note that the Notes sections of function descriptions are not definitive,
just suggestive. From Section 1.4.4.15 "The 'Notes' Section of a
Dictionary Entry":

Information not found elsewhere in this description which pertains to
this operator. Among other things, this might include cross reference
information, code equivalences, stylistic hints, implementation hints,
typical uses. This information is not considered part of the standard;
any conforming implementation or conforming program is permitted to
ignore the presence of this information.

In some cases, it may not even be possible for the code equivalence to be
really true. For instance, suppose there were a Note that said:

(function1 a b c d e f g h i j) == (funcall #'function2 a b c d e f g h i j)

If CALL-ARGUMENTS-LIMIT = 10, the lefthand side would be valid, but the
righthand side would not.

David D. Smith

unread,
Feb 3, 1998, 3:00:00 AM2/3/98
to

In article <30946931...@naggum.no>, Erik Naggum <cle...@naggum.no> wrote:

> although DELETE-IF-NOT and friends are deprecated, I find myself using
> them quite often and not really finding a much better replacement. what
> do people do when you want to delete an element that does not satisfy a
> particular predicate? is COMPLEMENT your choice?

I use -IF and -IF-NOT functions, and :TEST and :TEST-NOT keywords. I
don't use COMPLEMENT.

Here is an interesting approach I used in the kernel of GCLisp circa
1987... I showed this to KMP, and JonL, and I think I sent it to Steele.

(delete-if p s) => (delete f s :test #'funcall)
(delete-if-not p s) => (delete f s :test-not #'funcall)

You might think to do this like:

(defun delete-if (p s &rest keys)
(apply #'delete p s :test #'funcall keys))

Actually you have to list the keys since...

(delete-if p s :allow-other-keys t :test 1 :test-not 2) ;is OK, but

(delete p s :test #'funcall :allow-other-keys t :test 1 :test-not 2) ;is not


In GCLisp in the actual -IF and -IF-NOT functions I parsed the keywords
per standard, and then joined common code for all three functions with the
TEST slot containing the equivalent of #'FUNCALL.

-Duncan

David D. Smith

unread,
Feb 3, 1998, 3:00:00 AM2/3/98
to

In article <dds-030298...@p63.bit-net.com>, d...@flavors.com (David
D. Smith) wrote:

> (delete-if p s) => (delete f s :test #'funcall)
> (delete-if-not p s) => (delete f s :test-not #'funcall)

I meant:

(delete-if p s) => (delete p s :test #'funcall)
(delete-if-not p s) => (delete p s :test-not #'funcall)

-Duncan

0 new messages