Adam> (loop for i from 1 to 10 Adam> collect i Adam> collect 11)
After a FINALLY you have to put a compound-form (a Lisp expression, rather than a LOOP keyword), except that you are getting faked out because you know that RETURN is allowed there (as a special case).
The consequences of the code FINALLY COLLECT are undefined, but your implementation (CLISP I bet) happens to handle this by just totally ignoring the bogus FINALLY clause.
Adam> Is it just not possible to collect final values in the loop epilogue?
(loop for i from 1 to 10 collecting i into foo finally return (nconc foo '(11)))
> (loop for i from 1 to 10 > collect i > collect 11)
> Is it just not possible to collect final values in the loop epilogue?
Well what you actually tried to do is more like
(loop for i from 1 to 10 collect i into nums finally (return (nconc nums (list i))))
But I'm not sure if accessing i in the finally clause actually should lead to a 10 or an 11 at the end of the list. I've tried to check it in the HyperSpec but did not find something about that.
>>>>>> On Sat, 14 Sep 2002 15:10:06 +1200, Adam Warner ("Adam") writes: > Adam> Hi all, > Adam> Can someone please explain why the finally clause > Adam> below doesn't execute after normal iteration terminates:
> Adam> (loop for i from 1 to 10 > Adam> collect i > Adam> finally collect 11)
> Adam> (loop for i from 1 to 10 > Adam> collect i > Adam> collect 11)
> After a FINALLY you have to put a compound-form (a Lisp expression, > rather than a LOOP keyword), except that you are getting faked out > because you know that RETURN is allowed there (as a special case).
> The consequences of the code FINALLY COLLECT are undefined, but your > implementation (CLISP I bet) happens to handle this by just totally > ignoring the bogus FINALLY clause.
Many thanks Christopher and Jochen. You're right it is CLISP and I would have learned a lot faster if it had signalled an error on the bogus clause.
> Adam> Is it just not possible to collect final values in the loop epilogue?
> (loop for i from 1 to 10 collecting i into foo > finally return (nconc foo '(11)))
Thanks. I had already done this (the last item isn't supposed to be a constant like the example above):
(nconc (loop ...) (list foo-last))
It turns out to be clearer and less verbose than the loop way!:
* Christopher C. Stacy | After a FINALLY you have to put a compound-form (a Lisp expression, | rather than a LOOP keyword), except that you are getting faked out | because you know that RETURN is allowed there (as a special case).
I see no such special case in the standard, only compound-forms.
-- Erik Naggum, Oslo, Norway
Act from reason, and failure makes you rethink and study harder. Act from faith, and failure makes you blame someone and push harder.
* Adam Warner wrote: > (loop for i from 1 to 10 > collect i > finally collect 11)
This is very questionable. finally takes *forms* not clauses (as does initially), so what you've actually written is probably interpreted as if you'd said:
(loop for i from 1 to 10 collect i finally nil collect 11)
But if I was implementing LOOP I would signal, at least, a warning in this case.
> Is it just not possible to collect final values in the loop epilogue?
> After a FINALLY you have to put a compound-form (a Lisp expression, > rather than a LOOP keyword), except that you are getting faked out > because you know that RETURN is allowed there (as a special case).
>>>>> On 14 Sep 2002 10:24:56 +0000, Erik Naggum ("Erik") writes:
Erik> * Christopher C. Stacy Erik> | After a FINALLY you have to put a compound-form (a Lisp expression, Erik> | rather than a LOOP keyword), except that you are getting faked out Erik> | because you know that RETURN is allowed there (as a special case).
Erik> I see no such special case in the standard, only compound-forms.
Hmm, I think you're probably right about that, but I was thinking about the language in 6.1.7.2 talks about "Clauses such as return,..." followed by "Such an explicit return inside the finally clause..." which makes it sound like there is some special hack for FINALLY RETURN.
The BNF definitely agrees with you that there is no such hack, so that ought to settle it. But the above language is a little bit confusing.
> After a FINALLY you have to put a compound-form (a Lisp expression, > rather than a LOOP keyword), except that you are getting faked out > because you know that RETURN is allowed there (as a special case).
Erik Naggum
> I see no such special case in the standard, only compound-forms.
Christopher C. Stacy
> Hmm, I think you're probably right about that, but I was thinking > about the language in 6.1.7.2 talks about "Clauses such as return,..." > followed by "Such an explicit return inside the finally clause..." > which makes it sound like there is some special hack for FINALLY RETURN.
> The BNF definitely agrees with you that there is no such hack, so that > ought to settle it. But the above language is a little bit confusing.
The first return is the return loop clause. The second is the return macro. So this case is unambiguous.
-- "Die ganzen Zahlen hat der liebe Gott gemacht; alles andere ist Menschenwerk." "God made the integers; all else is the work of man." -- Leopold Kronecker (1821-1891)
On the subject of standard LOOP vs desires, I would like to be able to concatenate iteration sequences. E.g. (loop as x in '(a b c) then from 1 to 3 then in '(d e f) collect x) ==> (a b c 1 2 3 d e f).
Would there be any easy way for me to add such a feature, or is there already such a feature I don't know about?
> On the subject of standard LOOP vs desires, I would like to be able to > concatenate iteration sequences. E.g. (loop as x in '(a b c) then > from 1 to 3 then in '(d e f) collect x) ==> (a b c 1 2 3 d e f).
(loop nconc (loop for x in '(a b c) collect x) nconc (loop for x from 1 to 3 collect x) nconc (loop for x in '(d e f) collect x) until t)
Is this what you are looking for?
-- "Die ganzen Zahlen hat der liebe Gott gemacht; alles andere ist Menschenwerk." "God made the integers; all else is the work of man." -- Leopold Kronecker (1821-1891)
* Software Scavenger | On the subject of standard LOOP vs desires, I would like to be able to | concatenate iteration sequences. E.g. (loop as x in '(a b c) then from 1 to | 3 then in '(d e f) collect x) ==> (a b c 1 2 3 d e f).
Consider a function `range´
(defun range (from to) (loop for i from from to to collect i))
You could use it like this:
(loop for x in `(a b c ,@(range 1 3) d e f) ...).
-- Erik Naggum, Oslo, Norway
Act from reason, and failure makes you rethink and study harder. Act from faith, and failure makes you blame someone and push harder.
Oh no! dumb-loop, which you expect to be a list of 11 numbers is returning a different result each time.
You can no longer rely upon the quoted 11 to be 11 any more. It is destructively modified when linking the lists together, but this only becomes apparent when it is no longer the last term in the list construction.
I suggest the above loop should at least have been coded this way:
(nconc (loop for i from 1 to 10 collect i) (list 11))
Which agrees with Timothy Moore's recent comment in another thread: "That quoted list is constant. If you're going to fool around with nconc (and I don't see what you find so distasteful about the use of append) better try (nconc list (list 'element))."
wb...@gmx.net (Wolfhard Buß wrote in message <news:m3znuk9tjc.fsf@buss-14250.user.cis.dfn.de>... > (loop nconc (loop for x in '(a b c) collect x) > nconc (loop for x from 1 to 3 collect x) > nconc (loop for x in '(d e f) collect x) > until t) And Erik Naggum wrote: > (loop for x in `(a b c ,@(range 1 3) d e f) ...).
Both of those solve the problem in my example, but it was intended to be an example of a more general problem. There are often situations where the first iteration or two, and/or the last iteration or two, of a long sequence which might run in parallel with other long sequences in the same loop, need something special. As it is now, the code to handle those special cases can make the whole loop form longer and messier. It would be nice to find some completely general way to tell it to iterate through one sequence and then another and then another, without sacrificing any of the other features or conveniences of loop.
>>> (nconc (loop for i from 1 to 10 collect i) >>> '(11))
>> I suggest the above loop should at least have been coded this way:
>> (nconc (loop for i from 1 to 10 collect i) >> (list 11))
> Frankly, I would just have avoided the whole issue by writing > it this way:
> (loop for i from 1 to 11 collect i)
Thanks for letting me sample your wit here and via email Steven ;-)
The issue was adding a final term to a list. As I wrote earlier in the thread:
Thanks. I had already done this (the last item isn't supposed to be a constant like the example above):
(nconc (loop ...) (list foo-last))
I provided the note on the effect of using nconc & quoted values for the benefit of people learning Lisp. By your humorous rationale I could have avoided the whole issue of using loop by writing:
* Software Scavenger | Both of those solve the problem in my example, but it was intended to be an | example of a more general problem.
Both solutions were, I think, intended to solve the more general problem, but I now see that your major gripe is not the loss of features of `loop´, but consing up a brand new list, and this is a more valid concern in my view. The even more general problem than we solved would thus be a case such as
(loop for code from 32 to 95 then from 160 to 255 do (... something with ISO 8-bit character set conventsions ...))
which would certainly be more convenient than, say,
(loop for code from 32 to 255 unless (< 95 code 160) ...)
So I am sympathetic to your request now that I understand your goal better.
The `loop´ macro is normally supplied in source form with your Common Lisp implementation, so it should be possible to modify it locally, with all the drawbacks that has. I concur that some community effort to define such a mechanism would be useful, and it should be addable without serious compatibility problems because `then´ is not a valid clause.
-- Erik Naggum, Oslo, Norway
Act from reason, and failure makes you rethink and study harder. Act from faith, and failure makes you blame someone and push harder.
* Software Scavenger wrote: > On the subject of standard LOOP vs desires, I would like to be able to > concatenate iteration sequences. E.g. (loop as x in '(a b c) then > from 1 to 3 then in '(d e f) collect x) ==> (a b c 1 2 3 d e f).
Yes, I've wanted this - particularly something like:
(loop for x in '(1 2 3) then from 1 to 10 then on '(1 2 3) ...)
I don't think that there is a standard way of doing this other than simply doing something to create an object with is the `concatenation' of all these things. Some versions of LOOP have a way of defining new clauses, so one could probably use that to define something like this (I'm not sure if you could use `for' though?).
Erik Naggum wrote: > because `then´ is not a valid clause.
it is not a valid preposition.
-- Janos Blazi
-----------== Posted via Newsfeed.Com - Uncensored Usenet News ==---------- http://www.newsfeed.com The #1 Newsgroup Service in the World! -----= Over 100,000 Newsgroups - Unlimited Fast Downloads - 19 Servers =-----
Adam Warner wrote: > Thanks for letting me sample your wit here and via email Steven ;-)
Well, I trolled and hooked you, so now I'll give some serious advice. ;-)
(Digression: I learned just this weekend that Scott Fahlman, one of the CLtL1 Gang of Five, and a productive member of X3J13, Chair of the "Cleanup Committee", is believed to be the inventor of the ":-)" emoticon. See http://news.com.com/2100-1023-957817.html?tag=fd_top )
When X3J13 adopted the LOOP macro, it was a devisive and contested decision. There was a subcommittee on iteration that did the study of iteration system proposals. I vaguely remember the vote was only something like 60/40. Most X3J13 decisions of such grand importance were more-decisively for or against.
The argument against the non-simple LOOP was that it had irregular, un-lispy syntax, was hard to read in complex cases, and therefore didn't always do what the programmer expected. The argument in favor was mostly that LOOP was well understood in practice, there was a lot of existing code that used it, and that it was something that a significant portion of practicing near-CL programmers would expect to use in their code. The latter argument carried (and I was one voting in favor). I personally use lloop, and like the kinds of things it expresses concisely and eloquently. I also recursively macroexpand any nontrivial loop I write before compiling to make sure it really does what I think it does. So you can see that I agree with both sides in the original dispute; but I think it is good to have non-simple LOOP in the language, just like it is good to have format strings. (Nearly every argument against LOOP can be applied verbatim against format strings.)
But there were two other proposed iteration systems that contended with the historical LOOP macro: One was Richard Waters' (or Pretty Printer fame) "Series" package, and the other was "Generators and Gatherers" by Waters and Crispin Purdue, which (IIRC) was a later proposal based on experience with Series. Both were more Lispy and functional than the macro swamp of LOOP.
Neither of these was adopted, although the committee generally felt that both were technically, conceptually, linguistically, and morally superior to LOOP. The difficulty (IIRC) was that there was less experience using these systems, and perhaps they needed more exercise and trials with efficient implementation before being committed to the standard. The committee (IIRC) generally hoped that these would be kept available in portable packages, and perhaps optimized by implementors, so that they could be used and perhaps later become a regular part of the langauge. They are not part of the ANSI standard, but there are good writeups of these two packages in CLtL2, appendixes A and B respectively.
I know that the series package is readily available on the web. Check http://series.sourceforge.net/ and other standard places.
Anyway, I expect the kind of things you want to express are natural and idiomatic in series.
> The consequences of the code FINALLY COLLECT are undefined, but your > implementation (CLISP I bet) happens to handle this by just totally > ignoring the bogus FINALLY clause.
Future versions of CLISP will give a warning about this code.