From: Erik Naggum
Subject: COMPLEMENT and -IF-NOT functions
Date: 
Message-ID: <3094693129413453@naggum.no>
  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/

From: Pierpaolo Bernardi
Subject: Re: COMPLEMENT and -IF-NOT functions
Date: 
Message-ID: <6aiceq$18vi$2@serra.unipi.it>
Erik Naggum (······@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.
From: Michael Greenwald
Subject: Re: COMPLEMENT and -IF-NOT functions
Date: 
Message-ID: <michaelg.885832410@Xenon.Stanford.EDU>
········@cli.di.unipi.it (Pierpaolo Bernardi) writes:

>Erik Naggum (······@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.
From: Pierpaolo Bernardi
Subject: Re: COMPLEMENT and -IF-NOT functions
Date: 
Message-ID: <6aiiau$1hro$1@serra.unipi.it>
Michael Greenwald (········@Xenon.Stanford.EDU) wrote:
: ········@cli.di.unipi.it (Pierpaolo Bernardi) writes:

: >Erik Naggum (······@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.
From: Erik Naggum
Subject: Re: COMPLEMENT and -IF-NOT functions
Date: 
Message-ID: <3094829140346976@naggum.no>
* 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
-- 
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/
From: Erik Naggum
Subject: Re: COMPLEMENT and -IF-NOT functions
Date: 
Message-ID: <3094842811931093@naggum.no>
* Sam Steingold <···@usa.net>
| >>>> In a very interesting message <················@naggum.no>
| >>>> Sent on 26 Jan 1998 18:45:40 +0000
| >>>> Honorable Erik Naggum <······@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.  :)

#: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/
From: Pierpaolo Bernardi
Subject: Re: COMPLEMENT and -IF-NOT functions
Date: 
Message-ID: <6al5un$seu$1@serra.unipi.it>
Erik Naggum (······@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
: -- 
: 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/
From: Erik Naggum
Subject: Re: COMPLEMENT and -IF-NOT functions
Date: 
Message-ID: <3094920521318311@naggum.no>
* 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
From: Pierpaolo Bernardi
Subject: Re: COMPLEMENT and -IF-NOT functions
Date: 
Message-ID: <6amu43$tm8$2@serra.unipi.it>
Erik Naggum (······@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
: -- 
: 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
From: Erik Naggum
Subject: Re: COMPLEMENT and -IF-NOT functions
Date: 
Message-ID: <3094998414487754@naggum.no>
* 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.

#: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
From: Barry Margolin
Subject: Re: COMPLEMENT and -IF-NOT functions
Date: 
Message-ID: <SWPz.28$Ey4.493002@cam-news-reader1.bbnplanet.com>
In article <················@naggum.no>, Erik Naggum  <······@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, ······@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.
From: Erik Naggum
Subject: Re: COMPLEMENT and -IF-NOT functions
Date: 
Message-ID: <3095034865019317@naggum.no>
* 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
-- 
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
From: Pierpaolo Bernardi
Subject: Re: COMPLEMENT and -IF-NOT functions
Date: 
Message-ID: <6at2ig$c8p$2@croci.unipi.it>
Erik Naggum (······@naggum.no) wrote:
: * 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>


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
: -------
: � although interns appear to be no exception elsewhere
: -- 
: 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
From: Kelly Murray
Subject: Re: COMPLEMENT and -IF-NOT functions
Date: 
Message-ID: <6at7df$dsh$1@news2.franz.com>
> (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  ···@franz.com 
(btw, compliment was not spelled correctly)
From: Barry Margolin
Subject: Re: COMPLEMENT and -IF-NOT functions
Date: 
Message-ID: <UEpA.77$Ey4.1741180@cam-news-reader1.bbnplanet.com>
In article <············@croci.unipi.it>,
Pierpaolo Bernardi <········@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.

-- 
Barry Margolin, ······@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.
From: Pierpaolo Bernardi
Subject: Re: COMPLEMENT and -IF-NOT functions
Date: 
Message-ID: <6at1t7$c8p$1@croci.unipi.it>
Erik Naggum (······@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
: -- 
: 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
From: Pierpaolo Bernardi
Subject: Re: COMPLEMENT and -IF-NOT functions
Date: 
Message-ID: <6amrh6$tm8$1@serra.unipi.it>
Michael Greenwald (········@Xenon.Stanford.EDU) wrote:

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

   >Michael Greenwald (········@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-)