Thanks for the quick responses on my error handling question! They helped a lot. I have another question. Is there a function or macro which will do similar to what member-if does, but instead will return every element which passes the test?
I guess I could write a function to do it, but I think there might an existing one out there which will perform this? It seems like it would be a common operation on a list right?
Again, thanks for your help.
NC
-----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum
In article <6ttrts$qj...@nnrp1.dejanews.com>, <n...@hotmail.com> wrote: >Thanks for the quick responses on my error handling question! They helped a >lot. I have another question. Is there a function or macro which will do >similar to what member-if does, but instead will return every element which >passes the test?
Use REMOVE-IF and invert the sense of the test (using the COMPLEMENT function, if necessary). This supercedes the deprecated REMOVE-IF-NOT function.
>>(this_function #'integerp '(1 a 2 b 3 c)) >(1 2 3)
(remove-if (complement #'integerp) '(1 a 2 b 3 c))
-- Barry Margolin, bar...@bbnplanet.com GTE Internetworking, Powered by BBN, Burlington, MA *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
n...@hotmail.com wrote: > I have another question. Is there a function or macro which will do > similar to what member-if does, but instead will return every element which > passes the test?
(loop for i in '(1 2 3 4 5 6 7) when (oddp i) collect i)
> I guess I could write a function to do it, but I think there > might an existing > one out there which will perform this? It seems like it would > be a common > operation on a list right?
You're right. It does already exist:
(remove-if-not #'oddp '(1 2 3 4 5 6 7))
-- ________________________________________________________________ ^. Martti Halminen / \`. Design Power Europe Oy / \ `. Tekniikantie 12, FIN-02150 Espoo, Finland /\`. \ | Tel:+358 9 4354 2306, Fax:+358 9 455 8575 /__\|___\| Mailto:Martti.Halmi...@dpe.fi http://www.dpe.fi
> Thanks for the quick responses on my error handling question! They helped a > lot. I have another question. Is there a function or macro which will do > similar to what member-if does, but instead will return every element which > passes the test?
How about remove-if-not?
(remove-if-not #'oddp '(1 2 3 4 5 6 7 8))
=> (1 3 5 7)
> I tried > >(mapcar #'(lambda (x) (if (oddp x) x nil)) '(1 2 3 4 5 6 7)) > but I got > (1 NIL 3 NIL 5 NIL 7)
This is pretty close. You would have to use mapcaN instead of mapcaR and turn the value you want to collect into a list:
> I guess I could write a function to do it, but I think there might an existing > one out there which will perform this? It seems like it would be a common > operation on a list right?
I seems you will need to get your hands on a Common Lisp manual. It will help solve most of these problems.
BTW there is also a simple iterative solution using loop:
(loop for i in '(1 2 3 4 5 6 7 8) when (oddp i) collect i)
-- Thomas A. Russ, USC/Information Sciences Institute t...@isi.edu
* Barry Margolin <bar...@bbnplanet.com> | Use REMOVE-IF and invert the sense of the test (using the COMPLEMENT | function, if necessary). This supercedes the deprecated REMOVE-IF-NOT | function.
I find this a conceptually horrible suggestion. REMOVE-IF-NOT is at least possible to deal with as an idiom. REMOVE-IF of the COMPLEMENT of the function I really want in order to _keep_ certain elements is exactly how I would have force people to do things if I were into purity for its own sake and thought utility and pragmatics were stupid concerns.
not wanting to deal with the very annoying COMPLEMENT function, I have defined functions COLLECT and RETAIN as the semantic complements of REMOVE and DELETE, with -IF _and_ -IF-NOT variants. (COLLECT is a whole lot different from REMOVE with some keyword arguments, by the way.)
(defun collect-if (predicate list &rest keys) "Return a list of each element from LIST that satisfies PREDICATE. Accepts the same keyword arguments as REMOVE-IF." (apply #'remove-if-not predicate list keys))
I see no reason at all to deprecate -IF-NOT. the reason for deprecating :TEST-NOT is in a whole different category, since it is unspecified what :TEST FOO :TEST-NOT BAR should mean, i.e., when specified at the same time, and this problem _does_ come up when applying a function an unknown list of keyword-value pairs. no such thing could ever happen to -IF-NOT functions, yet it is apparent from the write-ups that -IF-NOT only got deprecated out of some misguided sense of symmetry with :TEST-NOT.
incidentally, the above function can be written with REMOVE-IF and the annoying COMPLEMENT function if one is so inclined. in any case, I think that if you think you need COMPLEMENT, you should define a new function that conveys the new purpose, and use that instead. it may well use COMPLEMENT internally. whether the new function is the test function or the caller of the test function depends on the purpose. the same goes for the all the other function-building functions that Dylan has and which it's sort of fun to play with, but which I think should not be used as open-coded idioms -- better to use them in implementations of something that reflects how you think.
#:Erik -- ATTENTION, all abducting aliens! you DON'T need to RETURN them!
In article <3115133657941...@naggum.no>, Erik Naggum <e...@naggum.no> wrote:
>* Barry Margolin <bar...@bbnplanet.com> >| Use REMOVE-IF and invert the sense of the test (using the COMPLEMENT >| function, if necessary). This supercedes the deprecated REMOVE-IF-NOT >| function.
> I find this a conceptually horrible suggestion.
It wasn't a suggestion, it was simply a statement of fact: ANSI CL specifies that the -IF-NOT functions are all deprecated. This was done as a concession to people who felt the language was bloated with unnecessary functions. Of course, there's nothing preventing the standards committee reversing itself in the future; if people ignore the deprecation and continue to make use of the -IF-NOT functions, it would make sense for the standard to agree with common practice, rather than gratuitously breaking everyone's code by removing them. On the other hand, if they do go through with removing them, users can't say they weren't warned years in advance.
-- Barry Margolin, bar...@bbnplanet.com GTE Internetworking, Powered by BBN, Burlington, MA *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
...Embracing an Open Systems Approach to Knowledge-based Engineering... -- David J Cooper Jr Genworks International dcoop...@genworks.com http://www.genworks.com
...Embracing an Open Systems Approach to Knowledge-based Engineering...
Barry Margolin <bar...@bbnplanet.com> writes: > In article <3115133657941...@naggum.no>, Erik Naggum <e...@naggum.no> wrote:
> > I find this a conceptually horrible suggestion.
So would I if not for the fact that these functions (or even their negations) aren't used much, and are totally easy to write yourself if missing.
It's clear the :TEST-NOT arguments are a semantic problem that has to be removed. (To see why, think about what happens when both :TEST-NOT and :TEST are supplied.) But the -IF-NOT functions are in more of a gray area. They are not semantically bankrupt--just rarely used. Perhaps by the time any change could be made, the space they take up will be of less importance.
> if they do go through > with removing them, users can't say they weren't warned years in advance.
Precisely. It's not a promise to remove them. It just reserves the right to discuss it without breaking people's programs.
And users aren't exactly screwed if they do go away some year. I didn't test the following, but imagine it or something like it would work, both today and years from now when remove-if-not goes away.
(defmacro define-if-not (not-function function) ;; Slight kludge warning: This assumes a compile-time check is good ;; enough. In principle, the compile time might differ from the ;; runtime, and normally one doesn't make the test for a runtime ;; situation at compile-time, but in the case of standards, the ;; compiler and run-time usually agree. (unless (fboundp not-function) ; assume compile-time check is close enough `(progn (proclaim '(inline ,not-function)) (defun ,not-function (predicate sequence &rest keys &key &allow-other-keys) (apply #',function (complement predicate) sequence keys)) ',not-function)))
Anyway, my point is that the few users who even use these functions can EASILY compensate for their absence. And probably, if/when we do remove them, we'll somewhere publish the workaround code so users don't even have to do that much work.
* Kent M Pitman <pit...@world.std.com> | So would I if not for the fact that these functions (or even their | negations) aren't used much, and are totally easy to write yourself | if missing.
"it's easy to write it yourself" is the Scheme argument. for a single function, it's hard to refute, except for "why _should_ programmers everywhere need to do it for themselves?". multiplied by thousands of functions, it doesn't really work that well, anymore. moreover, I have yet to see an implementation that does away with the closure consing and function call overhead of COMPLEMENT in _all_ cases, which I doubt is even possible, so to write these functions _well_ would require writing the internals yourself, or you penalize people for their needs. that's not what I associate with Common Lisp.
a quick scan of my last project's source (120K, kept small through very hard work), shows that I found these -IF-NOT functions useful:
DELETE-IF-NOT of UPPER-CASE-P, to retain initials REMOVE-IF-NOT of UPPER-CASE-P POSITION-IF-NOT of WHITESPACE-CHAR-P (for a non-consing TRIM) MEMBER-IF-NOT of EMPTY, a test for a blank line, etc and of NULL, to remove initial NILs in a list
in all of these cases, I would either cons up a closure with COMPLEMENT, write a new function with the reversed sense without closure consing or extra function call overhead, or _hope_ there's a compiler macro that reverts to internal -IF-NOT functions. what, precisely, is gained by removing these functions? I'd say "purity of design", and that would have been valid if such was an expressed goal of the language, and it didn't have serious costs associated with it.
| It's clear the :TEST-NOT arguments are a semantic problem that has to be | removed.
as I have already stated, but once again for the record: :TEST-NOT should go, and this I have thought for years. removing :TEST-NOT would not be done out of "purity of design" concerns, but out of concern for the fuzzy semantics of specifying both :TEST and :TEST-NOT, which might easily happen when writing the kind of functions that are suggested replacements for REMOVE-IF-NOT. since that is possible, we have a real conflict that cries out for a solution. I don't _like_ the name "complement" at all, but if I can bury it sufficiently, I hope I won't notice it sticking out.
| And users aren't exactly screwed if they do go away some year. I | didn't test the following, but imagine it or something like it would | work, both today and years from now when remove-if-not goes away. | | (eval-when (:execute :compile-toplevel :load-toplevel) | (when (fboundp 'remove-if-not) | (pushnew :remove-if-not *features*))) | | #-remove-if-not | (proclaim '(inline remove-if-not)) ;avoid overhead of extra function call | | #-remove-if-not | (defun remove-if-not (predicate sequence &rest keys &key &allow-other-keys) | (apply #'remove-if (complement predicate) sequence keys))
once upon a time, you said something to the effect that Common Lisp saved you heaps of code that you previously had had to add to every project. we're moving backwards, now, where people have to add such code. users _are_ screwed in many ways by this COMPLEMENT business. debuggability goes down, performance is hit, etc, etc. to re-supply REMOVE-IF-NOT after X3J13 takes it away needs reimplementing the function, not just slapping a couple wrappers around existing functions and hope nobody will notice that they can no longer fix bugs in the predicate function and continue, or that APPLY crops up much more often than it should during profiling. an implementation that sports compiler macros that attempt to make REMOVE-IF fast by pre-determining keyword arguments would not be able to optimize the call unless COMPLEMENT itself were to be used in the _actual_ form. thus, you make code much less readable in order to save on a "bloat" factor that is about two order of magnitude smaller than that of C++ or Java.
| Anyway, my point is that the few users who even use these functions can | EASILY compensate for their absence.
I take it that no study of the effects of the introduction of COMPLEMENT has been made. COMPLEMENT has _very_ high costs. they have _not_ been defended, nor have they been compared to the gains from removing -IF-NOT, if any. as I see it, COMPLEMENT is a wanton waste of resources. I have no qualms about spending lots of resources for a good reason; it's only the _wanton_ part I object to.
| And probably, if/when we do remove them, we'll somewhere publish the | workaround code so users don't even have to do that much work.
well, _I'm_ certain that vendors will protect user investments even if the committee abandons that goal.
take :TEST-NOT and be satisfied, is my suggestion. don't touch -IF-NOT.
#:Erik -- ATTENTION, all abducting aliens! you DON'T need to RETURN them!
Erik Naggum <e...@naggum.no> wrote: > I find this a conceptually horrible suggestion. REMOVE-IF-NOT is at > least possible to deal with as an idiom. REMOVE-IF of the COMPLEMENT of > the function I really want in order to _keep_ certain elements is exactly
^^^^^^
> how I would have force people to do things if I were into purity for its > own sake and thought utility and pragmatics were stupid concerns.
the readability argument: instead of your collect-if I named mine KEEP-IF. this a LOT more readable than remove-if-not, which is itself a lot more readable than (remove-if (complement ..) ..) or the :TEST-NOT key reading negations instead of their positive synonyms is like watching a woody allen movie.
but collect-if is also a good name. i just watched myself reading my code with the unspoken words "keep if" so i named it like this. you, erik, explained it the same way :)
* Reini Urban <rur...@sbox.tu-graz.ac.at> | but collect-if is also a good name. i just watched myself reading my | code with the unspoken words "keep if" so i named it like this. you, | erik, explained it the same way :)
hm. I intended "keep" as a generalized term encompassing both "collect" and "retain", the point being that COLLECT would return a freshly consed list of elements collected from the argument list, while RETAIN would (destructively) delete the unwanted elements from the argument list.
#:Erik -- ATTENTION, all abducting aliens! you DON'T need to RETURN them!
> area. They are not semantically bankrupt--just rarely used.
I personally find that I use REMOVE-IF-NOT *much* more than REMOVE-IF. And I personally find that REMOVE-IF-NOT is conceptually more of a primitive than REMOVE-IF. The name not withstanding. REMOVE-IF-NOT is often called by other names: e.g. FILTER, SUCH-THAT, etc. More often than not, I find that I want a list of elements that satisfies some predicate (which is what REMOVE-If-NOT yields), not a list of elements that does not satisfy some predicate (which is what REMOVE-IF yields).
The issue is whether to view the function operationally (what to remove) or declaratively (what property the result has). I personally prefer the later and find that it makes code more readable.
In article <3115185220022...@naggum.no>, Erik Naggum <e...@naggum.no> wrote: > * Kent M Pitman <pit...@world.std.com> > | So would I if not for the fact that these functions (or even their > | negations) aren't used much, and are totally easy to write yourself > | if missing.
> "it's easy to write it yourself" is the Scheme argument. for a single > function, it's hard to refute, except for "why _should_ programmers > everywhere need to do it for themselves?". multiplied by thousands of > functions, it doesn't really work that well, anymore. moreover, I have > yet to see an implementation that does away with the closure consing and > function call overhead of COMPLEMENT in _all_ cases, which I doubt is > even possible, so to write these functions _well_ would require writing > the internals yourself, or you penalize people for their needs. that's > not what I associate with Common Lisp.
I second this POV and will also say that I frequently use local functions as these arguments, which tends to compound the problem.
> a quick scan of my last project's source (120K, kept small through very > hard work), shows that I found these -IF-NOT functions useful:
> DELETE-IF-NOT of UPPER-CASE-P, to retain initials > REMOVE-IF-NOT of UPPER-CASE-P > POSITION-IF-NOT of WHITESPACE-CHAR-P (for a non-consing TRIM) > MEMBER-IF-NOT of EMPTY, a test for a blank line, etc > and of NULL, to remove initial NILs in a list
A review of our Paracell Navigator shows 17 calls to -IF-NOT functions, including COUNT, REMOVE, DELETE, POSITION, MEMBER, and FIND. Additionally there are 10 calls using :TEST-NOT.
> in all of these cases, I would either cons up a closure with COMPLEMENT, > write a new function with the reversed sense without closure consing or > extra function call overhead, or _hope_ there's a compiler macro that > reverts to internal -IF-NOT functions. what, precisely, is gained by > removing these functions? I'd say "purity of design", and that would > have been valid if such was an expressed goal of the language, and it > didn't have serious costs associated with it.
If "purity of design", whatever that means, ever becomes the primary goal in the specification of Common LISP, it will be doomed as a commercial language. I am a pragmatists of a sort and I use Common LISP because I get the the most work done for the least time spent. Please don't make me waste the time to reinvent all those functions and features that others have done so well, just because it satisfies someones notion of "purity of design".
> | It's clear the :TEST-NOT arguments are a semantic problem that has to be > | removed.
Kent,
It is not at all clear to me. If you are concerned with the overhead it implies, I would suggest the following: Change the simultaneous :TEST / :TEST-NOT problem from an ERROR to a case of "Undefined Behavior" and let the user accept responsibility for it, with the implementation free to pick the leftmost perhaps.
As I showed you (about 10 years ago at Encore), and showed others on the list here. All the -IF-NOT functions can be implemented in terms of :TEST-NOT #'FUNCALL. As can the -IF functions in terms of :TEST #'FUNCALL. This is another reason why the Space argument is a less persuasive reason to expunge these. BTW, I noticed at the time (at Encore) that Lucid had big huge expansions for each of the -IF and -IF-NOT functions, with no code sharing...
Documentation is DONE.
Maintenence is hardly required for these functions.
> [...] If you are concerned with the overhead it > implies, I would suggest the following: Change the simultaneous :TEST / > :TEST-NOT problem from an ERROR to a case of "Undefined Behavior" and let > the user accept responsibility for it, with the implementation free to > pick the leftmost perhaps.
No. The time part doesn't bother me at all. It's that I think having both creates an aomalous situation where if someone does (defun frob (&rest keys) (apply #'find-if :test #'eql keys)) which is the normal idiom for overriding a :test argument in a set of keys, you don't know if you really merged it right. This isn't about efficiency, it's about predictability. THere is an efficiency argument, but I don't find it the key issue. To me, the "undefined" ploy is only allowable when normal uses allow you to tell you're doing it.
Keyword cascading/overriding may not be common among readers of this list, I don't know; but I know places where it's very common. We were really fixing a bug in fixing the :test and :test-not stuff. The same can't be said of -IF-NOT, which I identified as being in a gray area and which I think the committee deprecated mostly for perceived consistency.
(Wouldn't be the first time we got it wrong on "apparent consistency". The one that drives me nuts is the "you can't repeat an argument in a bound variable list" rule as applied to LET*, for which you really ought to be able to.)
FWIW, I'm pretty much swayed by very useful evidence offered in this discussion that the -IF-NOT functions should not go away. So anyone who wants to argue for keeping them isn't talking to me.
Kent Pitman wrote: > No. The time part doesn't bother me at all. It's that I think having both > creates an aomalous situation where if someone does > (defun frob (&rest keys) (apply #'find-if :test #'eql keys)) > which is the normal idiom for overriding a :test argument in a set of keys, > you don't know if you really merged it right. This isn't about efficiency, > it's about predictability.
I don't understand why this wouldn't be solved perfectly adequately by saying that the *rightmost* :TEST or :TEST-NOT takes precedence.
-- Gareth McCaughan Dept. of Pure Mathematics & Mathematical Statistics, gj...@dpmms.cam.ac.uk Cambridge University, England.