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
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.
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.
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/
: 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
berna...@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.
: >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.
"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/
* Sam Steingold <s...@usa.net> | >>>> In a very interesting message <3094829140346...@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. :)
#: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/
: "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/
* 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
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).
: * 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
* 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
In article <3094998414487...@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.
* 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 ...
#: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
: * 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
: * 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:
: 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 ...
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
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, 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.
In article <3094693129413...@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.