|
|
|
Martin Piskernig
|
Hi!
I think it would be very helpful if you could add some kind of a "for each" loop, that traverses collections element by element, to Eiffel. I really miss it as a quick and powerful (syntactical) tool when often switching from Java to Eiffel. In Eiffel I usually have to write: ... local elem:T ... from list.start until list.off loop elem := list.item ... do something with elem ... list.forth end This could be much abbreviated to: for list as elem loop ... do something with elem ... end (or whatever keyword you like instead of "for", that's not the point) The foreach loop should be possible for every collection that inherits from TRAVERSABLE, or rejected by the compiler otherwise. I have read that, in the past, new variants of loops have been rejected because of some principle that says that in Eiffel there should be exactly ony way to "do it". This principle does not seem sound to me in that it is broken in many ways by Standard Eiffel ("if" vs. "inspect", "what" note vs. header comment, etc.). Regards, Martin |
||||||||||||||||
|
peter7723
|
--- In [hidden email], Martin Piskernig <martin.piskernig@...> wrote:
> > Hi! > > I think it would be very helpful if you could add some kind of a "for > each" loop, that traverses collections element by element, to Eiffel. The features do_all, do_if, there_exists and for_all are supplied in class TRAVERABLE[G] and in class ARRAY[G]. So, you can write list.do_all(agent item_procedure_feature) which will execute item.item_procedure_feature for every item. Peter Horan |
||||||||||||||||
|
rfo
|
In reply to this post
by Martin Piskernig
Hi Martin
You might (in the mean time :)) have a look at the iterators within the containers. They can be handy for simple loops over contents. Have a look at LINEAR's do_all, do_if, and for_all features. R ================================================== Roger F. Osmond > -------- Original Message -------- > Subject: [eiffel_software] "for each" loop? > From: Martin Piskernig <[hidden email]> > Date: Fri, September 18, 2009 7:08 pm > To: [hidden email] > Hi! > I think it would be very helpful if you could add some kind of a "for > each" loop, that traverses collections element by element, to Eiffel. I > really miss it as a quick and powerful (syntactical) tool when often > switching from Java to Eiffel. > In Eiffel I usually have to write: > ... > local > elem:T > ... > from list.start until list.off loop > elem := list.item > ... do something with elem ... > list.forth > end > This could be much abbreviated to: > for list as elem loop > ... do something with elem ... > end > (or whatever keyword you like instead of "for", that's not the point) > The foreach loop should be possible for every collection that inherits > from TRAVERSABLE, or rejected by the compiler otherwise. > I have read that, in the past, new variants of loops have been rejected > because of some principle that says that in Eiffel there should be > exactly ony way to "do it". This principle does not seem sound to me in > that it is broken in many ways by Standard Eiffel ("if" > vs. "inspect", "what" note vs. header comment, etc.). > Regards, > Martin |
||||||||||||||||
|
Bertrand Meyer
|
In reply to this post
by Martin Piskernig
There is a proposal for an extension to the loop syntax which will provide
this mechanism. It should be available in experimental form (prior to adoption by the Ecma committee) soon. As soon as I have a minute I will post a blog entry about it. -- BM From: [hidden email] [mailto:[hidden email]] On Behalf Of Martin Piskernig Sent: 19 September, 2009 01:09 To: [hidden email] Subject: [eiffel_software] "for each" loop? Hi! I think it would be very helpful if you could add some kind of a "for each" loop, that traverses collections element by element, to Eiffel. I really miss it as a quick and powerful (syntactical) tool when often switching from Java to Eiffel. In Eiffel I usually have to write: ... local elem:T ... from list.start until list.off loop elem := list.item ... do something with elem ... list.forth end This could be much abbreviated to: for list as elem loop ... do something with elem ... end (or whatever keyword you like instead of "for", that's not the point) The foreach loop should be possible for every collection that inherits from TRAVERSABLE, or rejected by the compiler otherwise. I have read that, in the past, new variants of loops have been rejected because of some principle that says that in Eiffel there should be exactly ony way to "do it". This principle does not seem sound to me in that it is broken in many ways by Standard Eiffel ("if" vs. "inspect", "what" note vs. header comment, etc.). Regards, Martin [Non-text portions of this message have been removed] |
|
rfo
|
In reply to this post
by Martin Piskernig
Hello Bertrand!
Quite a while ago I asked for your impression regarding a proposal I had tossed around with Manu regarding increment/decrement operators and using them to add a for-loop like option to the Eiffel loop constuct. I'm pretty sure I never gave you the original text on that discussion. Well, after some searching, inspired by the most recent query on the yahoo group, I found the original, posted in March of 2007 to the dev.eiffel.com site as "Auto-Increment_Proposal" (with 1,371 accesses to date). Don't let the title fool you, it's more about loops. The original intent of the proposal was to add an increment operator. What was different was the concept of treating integers (and characters) as values in a predictable sequence, rather than simply as values in a vaccuum. This thinking leads to "forth" and "back" functions, where an integer.forth would move the integer object forth along the number line to the next value. A character.forth would move the object's value forward on step in its collating sequence. Model wise, I guess integers would be BILINEAR and INFINITE, in that they could be traversed forth and back, but never finish. They could be further qualified as having a median or origin of 0. Characters would be finite, bounded by their collating sequences. This leads us to the loop enhancements, adding an increment clause to the current loop construct. If traversable lists, linear structures and integers shared common ancestors that provided the abstract notion of iteration (a la forth and back), then it should be possible to add to the loop construct an expression that drives the loop iteration - the one missing piece. Here is an example. from i := 1 until i > 5 by i.forth loop {loop body} end The 'by' keyword introduces the iterator clause which includes the iterator statement to be executed on each loop iteration. In this case, it's a simple procedure call to i.forth. It can as easily be any statement, even an agent. I think the latter case opens up the possibility of creating a more usable external iterator class by the way, but that's a topic for another time. The same constuct works for a list, as in: from list.start until list.after by list.forth loop {loop body} end or a character, as in: from c := 'A' until c > 'Z' by c.forth loop {loop body} end Because the iterator clause is optional, there is no issue of backward compatibility. All existing (and future) loops without an iterator clause would be just fine. An alternative would have the iterator clause at the bottom of the loop. from i := 1 until i > 5 loop {loop body} by i.forth end While this more closely resembles the way a lot of code is written by hand, to my thinking it has less value because it splits the loop specification into 2 sections, possibly widely separated. It also adds confusion, in my mind. I much prefer the spec being all together at the top. It just reads better as a spec, and I think it would encourage forethought - resulting in more reliable loops. Leaving the iterator to the end is just asking for incomplete thinking. One interesting wrinkle is the do-while/while-do issue. Some loops will want the iterator to execute at the top, and others will want it to execute at the bottom. One might conclude that the latter supports the form I just said I hated, but it does not. It is possible to have both flavors, while keeping the loop specification clauses together. from i := 1 until i > 5 loop by i.forth {loop body} end Having the iterator clause after the loop keyword specifies that the iteration will occur after the body of the loop. Having the original form, with the iterator clause before the loop keyword specifies that the iteration will occur before the body of the loop. I can see how this might be confusing for some. Another alternative might be to borrow from conditions, and use 'then' to denote sequence, as in: from i := 1 until i > 5 loop then i.forth {loop body} end from i := 1 until i > 5 i.forth then loop {loop body} end The first form being at-bottom and the second form being at-top, Note well that the 'by' keyword is no longer needed in this form, as the 'then' keyword should be sufficient. This is my preferred form at the moment. Another option might be to drop the keyword altogether. The presence of a legitimate statement itself might be adequate. The construct then would look like this. from i := 1 until i > 5 i.forth -- Or i++ if such an alias exists loop (loop body) end I don't like this at all, but it does more closely resemble a for loop. I think it fails in just about every other way. How does all this impact loop-level assertions? I think there is potential to have a very positive impact. At present, loop assertions are a mystery to many. I use them, but not all the time (shame on me). Newbies simply freak out, especially when confronted with the rules for loop variants. By including the iterator statement in the loop spec, it should be possible to generate loop variants automatically (and correctly). Loop invariants remain as before. We could have another switch in the system configuration to enable automatic loop variant assertions. They would exist only for those loops with a complete specification - i.e. with an iterator expression. Those folks who use loops and indices the most I think would welcome this feature and the forth/++ extension to integer. R ================================================== Roger F. Osmond > -------- Original Message -------- > Subject: RE: [eiffel_software] "for each" loop? > From: Bertrand Meyer <[hidden email]> > Date: Sat, September 19, 2009 10:05 am > To: <[hidden email]> > There is a proposal for an extension to the loop syntax which will provide > this mechanism. It should be available in experimental form (prior to > adoption by the Ecma committee) soon. As soon as I have a minute I will post > a blog entry about it. > > -- BM > > From: [hidden email] > [mailto:[hidden email]] On Behalf Of Martin Piskernig > Sent: 19 September, 2009 01:09 > To: [hidden email] > Subject: [eiffel_software] "for each" loop? > > > Hi! > I think it would be very helpful if you could add some kind of a "for > each" loop, that traverses collections element by element, to Eiffel. I > really miss it as a quick and powerful (syntactical) tool when often > switching from Java to Eiffel. > In Eiffel I usually have to write: > ... > local > elem:T > ... > from list.start until list.off loop > elem := list.item > ... do something with elem ... > list.forth > end > This could be much abbreviated to: > for list as elem loop > ... do something with elem ... > end > (or whatever keyword you like instead of "for", that's not the point) > The foreach loop should be possible for every collection that inherits > from TRAVERSABLE, or rejected by the compiler otherwise. > I have read that, in the past, new variants of loops have been rejected > because of some principle that says that in Eiffel there should be > exactly ony way to "do it". This principle does not seem sound to me in > that it is broken in many ways by Standard Eiffel ("if" > vs. "inspect", "what" note vs. header comment, etc.). > Regards, > Martin > [Non-text portions of this message have been removed] |
||||||||||||||||
|
Bertrand Meyer
|
Dear Roger:
I see the usefulness of a “by” clause but am uneasy about its relationship to the “loop” clause. It is not always clear what is the body and what is the advance. For example in Euclid’s algorithm from x := a ; y := b invariant gcd (x, y) = gcd (a, b) until x = y loop if x > y then x := x – y else y := y –x end variant max (x, y) -- Or: x + y end the conditional instruction is both body and advance. Framing the matter in theory, any loop is of the following form, where S is a subset of the data: from “Establish INV on trivial subset S” invariant INV until “S is the entire data set” loop “Extend S so that INV holds on resulting S” -- [LB] variant “|Data - S|” -- i.e. size of subset of data not yet covered end where INV applied to the entire data is the desired postcondition. It is fairly common that the loop body [LB], “Extend S so that INV holds on resulting S”, naturally splits itself into a sequence of two actions: “Add items to S” -- [1] (This may break INV) “Fix state to ensure that INV holds on S” -- [2] In that case the distinction between body and advance is clear: [1] is the advance (“by” clause) and [2} is the body (“loop”). A simple example is the obvious loop to compute the sum of elements of an array or list of integers. But not all cases expand [LB] in such a straightforward ways. For examples that do not, I find the distinction between “loop” and “by” more confusing than helpful. You might like the proposed generalized iteration -- I will post about it. Thanks, -- BM From: [hidden email] [mailto:[hidden email]] On Behalf Of [hidden email] Sent: 19 September, 2009 17:29 To: [hidden email] Subject: RE: [eiffel_software] "for each" loop? Hello Bertrand! Quite a while ago I asked for your impression regarding a proposal I had tossed around with Manu regarding increment/decrement operators and using them to add a for-loop like option to the Eiffel loop constuct. I'm pretty sure I never gave you the original text on that discussion. Well, after some searching, inspired by the most recent query on the yahoo group, I found the original, posted in March of 2007 to the dev.eiffel.com site as "Auto-Increment_Proposal" (with 1,371 accesses to date). Don't let the title fool you, it's more about loops. The original intent of the proposal was to add an increment operator. What was different was the concept of treating integers (and characters) as values in a predictable sequence, rather than simply as values in a vaccuum. This thinking leads to "forth" and "back" functions, where an integer.forth would move the integer object forth along the number line to the next value. A character.forth would move the object's value forward on step in its collating sequence. Model wise, I guess integers would be BILINEAR and INFINITE, in that they could be traversed forth and back, but never finish. They could be further qualified as having a median or origin of 0. Characters would be finite, bounded by their collating sequences. This leads us to the loop enhancements, adding an increment clause to the current loop construct. If traversable lists, linear structures and integers shared common ancestors that provided the abstract notion of iteration (a la forth and back), then it should be possible to add to the loop construct an expression that drives the loop iteration - the one missing piece. Here is an example. from i := 1 until i > 5 by i.forth loop {loop body} end The 'by' keyword introduces the iterator clause which includes the iterator statement to be executed on each loop iteration. In this case, it's a simple procedure call to i.forth. It can as easily be any statement, even an agent. I think the latter case opens up the possibility of creating a more usable external iterator class by the way, but that's a topic for another time. The same constuct works for a list, as in: from list.start until list.after by list.forth loop {loop body} end or a character, as in: from c := 'A' until c > 'Z' by c.forth loop {loop body} end Because the iterator clause is optional, there is no issue of backward compatibility. All existing (and future) loops without an iterator clause would be just fine. An alternative would have the iterator clause at the bottom of the loop. from i := 1 until i > 5 loop {loop body} by i.forth end While this more closely resembles the way a lot of code is written by hand, to my thinking it has less value because it splits the loop specification into 2 sections, possibly widely separated. It also adds confusion, in my mind. I much prefer the spec being all together at the top. It just reads better as a spec, and I think it would encourage forethought - resulting in more reliable loops. Leaving the iterator to the end is just asking for incomplete thinking. One interesting wrinkle is the do-while/while-do issue. Some loops will want the iterator to execute at the top, and others will want it to execute at the bottom. One might conclude that the latter supports the form I just said I hated, but it does not. It is possible to have both flavors, while keeping the loop specification clauses together. from i := 1 until i > 5 loop by i.forth {loop body} end Having the iterator clause after the loop keyword specifies that the iteration will occur after the body of the loop. Having the original form, with the iterator clause before the loop keyword specifies that the iteration will occur before the body of the loop. I can see how this might be confusing for some. Another alternative might be to borrow from conditions, and use 'then' to denote sequence, as in: from i := 1 until i > 5 loop then i.forth {loop body} end from i := 1 until i > 5 i.forth then loop {loop body} end The first form being at-bottom and the second form being at-top, Note well that the 'by' keyword is no longer needed in this form, as the 'then' keyword should be sufficient. This is my preferred form at the moment. Another option might be to drop the keyword altogether. The presence of a legitimate statement itself might be adequate. The construct then would look like this. from i := 1 until i > 5 i.forth -- Or i++ if such an alias exists loop (loop body) end I don't like this at all, but it does more closely resemble a for loop. I think it fails in just about every other way. How does all this impact loop-level assertions? I think there is potential to have a very positive impact. At present, loop assertions are a mystery to many. I use them, but not all the time (shame on me). Newbies simply freak out, especially when confronted with the rules for loop variants. By including the iterator statement in the loop spec, it should be possible to generate loop variants automatically (and correctly). Loop invariants remain as before. We could have another switch in the system configuration to enable automatic loop variant assertions. They would exist only for those loops with a complete specification - i.e. with an iterator expression. Those folks who use loops and indices the most I think would welcome this feature and the forth/++ extension to integer. R ================================================== Roger F. Osmond > -------- Original Message -------- > Subject: RE: [eiffel_software] "for each" loop? > From: Bertrand Meyer <[hidden email] <mailto:Bertrand.Meyer%40inf.ethz.ch> > > Date: Sat, September 19, 2009 10:05 am > To: <[hidden email] <mailto:eiffel_software%40yahoogroups.com> > > There is a proposal for an extension to the loop syntax which will provide > this mechanism. It should be available in experimental form (prior to > adoption by the Ecma committee) soon. As soon as I have a minute I will post > a blog entry about it. > > -- BM > > From: [hidden email] <mailto:eiffel_software%40yahoogroups.com> > [mailto:[hidden email] <mailto:eiffel_software%40yahoogroups.com> ] On Behalf Of Martin Piskernig > Sent: 19 September, 2009 01:09 > To: [hidden email] <mailto:eiffel_software%40yahoogroups.com> > Subject: [eiffel_software] "for each" loop? > > > Hi! > I think it would be very helpful if you could add some kind of a "for > each" loop, that traverses collections element by element, to Eiffel. I > really miss it as a quick and powerful (syntactical) tool when often > switching from Java to Eiffel. > In Eiffel I usually have to write: > ... > local > elem:T > ... > from list.start until list.off loop > elem := list.item > ... do something with elem ... > list.forth > end > This could be much abbreviated to: > for list as elem loop > ... do something with elem ... > end > (or whatever keyword you like instead of "for", that's not the point) > The foreach loop should be possible for every collection that inherits > from TRAVERSABLE, or rejected by the compiler otherwise. > I have read that, in the past, new variants of loops have been rejected > because of some principle that says that in Eiffel there should be > exactly ony way to "do it". This principle does not seem sound to me in > that it is broken in many ways by Standard Eiffel ("if" > vs. "inspect", "what" note vs. header comment, etc.). > Regards, > Martin > [Non-text portions of this message have been removed] [Non-text portions of this message have been removed] |
||||||||||||||||
|
Bertrand Meyer
|
It seems the formatting of my message was lost. It should be more readable at
http://se.ethz.ch/~meyer/down/foreach.txt From: [hidden email] [mailto:[hidden email]] On Behalf Of Bertrand Meyer Sent: 19 September, 2009 19:22 To: [hidden email] Subject: RE: [eiffel_software] "for each" loop? Dear Roger: I see the usefulness of a “by” clause but am uneasy about its relationship to the “loop” clause. It is not always clear what is the body and what is the advance. For example in Euclid’s algorithm f [Non-text portions of this message have been removed] |
||||||||||||||||
|
Martin Piskernig
|
In reply to this post
by Bertrand Meyer
On Samstag, 19. September 2009, Bertrand Meyer wrote:
> There is a proposal for an extension to the loop syntax which will provide > this mechanism. It should be available in experimental form (prior to > adoption by the Ecma committee) soon. As soon as I have a minute I will > post a blog entry about it. Bertrand, thank you very much for your answer! I eagerly await your blog post :-) Kind regards, Martin ------------------------------------ Yahoo! Groups Links <*> To visit your group on the web, go to: http://groups.yahoo.com/group/eiffel_software/ <*> Your email settings: Individual Email | Traditional <*> To change settings online go to: http://groups.yahoo.com/group/eiffel_software/join (Yahoo! ID required) <*> To change settings via email: mailto:[hidden email] mailto:[hidden email] <*> To unsubscribe from this group, send an email to: [hidden email] <*> Your use of Yahoo! Groups is subject to: http://docs.yahoo.com/info/terms/ |
||||||||||||||||
| Free Embeddable Forum Powered by Nabble | Help |