• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Devaka Cooray
  • Ron McLeod
  • Jeanne Boyarsky
Sheriffs:
  • Liutauras Vilda
  • paul wheaton
  • Junilu Lacar
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Piet Souris
  • Carey Brown
  • Tim Holloway
Bartenders:
  • Martijn Verburg
  • Frits Walraven
  • Himai Minh

for-each thoughts

 
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It's the weekend, so I figured it might be fun to start a thread/rant (yes, another ).

Does anybody else feel that Java missed an opportunity by not introducing a 'foreach' keyword when they had a chance?

It seems to me that it would open several possibilities, the most obvious being:
foreach (int i = 0; someType t : someColllection; i++) { ...

but there's also:
foreach ([initializer;] boolean-expression; someType t : someColllection) { ...
and
foreach ([initializer;] someType t : someColllection; boolean-expression) { ...
as pre- and post-checked loops.

I'm certainly no compiler writer, so I don't know all the possible pitfalls, but it seems to me to be pretty straightforward.
Can anyone enlighten me as to the possible problems (name collisions with 'foreach' aside)?

Cheers.

Winston
 
Bartender
Posts: 2407
36
Scala Python Oracle Postgres Database Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:It seems to me that it would open several possibilities, the most obvious being:
foreach (int i = 0; someType t : someColllection; i++) { ...


I'm out of practice in Java, but what would be the advantage of this over the current Java "for" loops, and what's the point of the counter variable i here?

Winston Gutkowski wrote:but there's also:
foreach ([initializer;] boolean-expression; someType t : someColllection) { ...
and
foreach ([initializer;] someType t : someColllection; boolean-expression) { ...
as pre- and post-checked loops.


The "foreach" bit seems to be doing too much here, at least for my limited intellect. Anyway, I'm definitely too dumb to be allowed to play around with something like this - I get confused if I use a "++i" instead of "i++"! FWIW, I like the simple Groovy/Python "for each" approach of "for item in collection", although Groovy's "each" method on Lists is even neater. Java's current "for each" loop is OK too, but the type declarations make it a bit clunkier, as usual. As for counter loops, Groovy and Python both offer various ways to do this easily with integer ranges, not to mention list comprehensions etc. I wouldn't want to discourage you from raising a JSR for this, but I reckon Java's complicated enough for me already!
 
Sheriff
Posts: 3061
12
Mac IntelliJ IDE Python VI Editor Java
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The first one is a loop with index? That could be useful in some situations, but I guess the index would be misleading with certain kinds of collections, like a hash table. The second loop adds an early exit condition? I would use that a lot, because I often work in environments where the guideline not to return from the middle of a method body (or even to break out of a loop) has become a hard-and-fast rule.

The third looks like the second with the expressions in a different order. I'm not getting that one.
 
Bartender
Posts: 3323
86
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Does anybody else feel that Java missed an opportunity by not introducing a 'foreach' keyword when they had a chance?


Possibly but adding new a keyword does present the possibility of breaking existing code because for example someone has used 'foreach' as a variable name.
 
Sheriff
Posts: 22701
129
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That wasn't a problem for assert and enum.
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Greg Charles wrote:The first one is a loop with index? That could be useful in some situations, but I guess the index would be misleading with certain kinds of collections, like a hash table.


No more confusing than
for (someType t : someHashSet) { ...
surely? And quite useful for, eg, populating an array with the contents.
But I agree, somewhat more limited than with ordered collections.

The second loop adds an early exit condition? I would use that a lot, because I often work in environments where the guideline not to return from the middle of a method body (or even to break out of a loop) has become a hard-and-fast rule.


Exactly my point; although making it a rule seems a bit anal.

The third looks like the second with the expressions in a different order. I'm not getting that one.


Simply the difference between a while and a do...while.

HIH

Winston
 
Marshal
Posts: 76873
366
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think there is nothing wrong with the present for‑each loop. It should have been in Java1.1, however.
 
Sheriff
Posts: 3837
66
Netbeans IDE Oracle Firefox Browser
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
What I would like to do is to iterate two (or perhaps even more) equally-sized collections at once, something like:

This is the most usual situation in which I'm using indexed loop instead of for each loop.

It could terminate when first of the iterators runs out of items (solves the need for the collections to be equally sized, furthermore, Iterables don't have to know their sizes).

Hmmm, thinking about it, I'm probably going to write a ComboIterator<E, F> class which would take two iterators and allowed me to iterate over them in sync, using Combo<E, F> with methods E getFirst(), F getSecond().

It looks awful when written down. So maybe not after all.
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tony Docherty wrote:Possibly but adding new a keyword does present the possibility of breaking existing code because for example someone has used 'foreach' as a variable name.


I said 'aside from [that]'. Us ranters live in a perfect world, don't you understand?

Rob Spoor wrote:That wasn't a problem for assert and enum.


Ah, Vindication! Cheers for that. Now I await the 'but'...

Winston
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Martin Vajsar wrote:What I would like to do is to iterate two (or perhaps even more) equally-sized collections at once, something like:


Hmmm. Nice. I think the syntax would have to be clearly defined, but ... yeah. I'd vote for it.

Winston
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

chris webster wrote:I'm out of practice in Java, but what would be the advantage of this over the current Java "for" loops, and what's the point of the counter variable i here?


Basically, so you can define a counter that only has scope inside the loop. There are several situations where it could be useful; one of which I've already stated; but I think it would be useful for almost any kind of loop that involves a RandomAccess List (which must be close to half the Iterables we use ).

The "foreach" bit seems to be doing too much here, at least for my limited intellect.


Yeah, I can understand that; and maybe it is a bit too much, but the fact is that without a new keyword, we don't really have any choice in the matter.

FWIW, I like the simple Groovy/Python "for each" approach of "for item in collection", although Groovy's "each" method on Lists is even neater. Java's current "for each" loop is OK too, but the type declarations make it a bit clunkier, as usual. As for counter loops, Groovy and Python both offer various ways to do this easily with integer ranges, not to mention list comprehensions etc. I wouldn't want to discourage you from raising a JSR for this, but I reckon Java's complicated enough for me already!


Yup. I could go with that too: an each() method on an Iterable (or maybe an EachIterable sub-interface) that's always called by the for-each loop. Possibly a bit more OO too.

Needs a bit of fleshing out I think, but I like the idea.

Winston
 
Rob Spoor
Sheriff
Posts: 22701
129
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Martin Vajsar wrote:What I would like to do is to iterate two (or perhaps even more) equally-sized collections at once, something like:

This is the most usual situation in which I'm using indexed loop instead of for each loop.


I once suggested a shorter for-each syntax for Maps:
Or perhaps more like PHPSun (at the time) shot down this idea because of closures coming up.
 
Rancher
Posts: 4327
59
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Rob Spoor wrote:That wasn't a problem for assert and enum.


Um, sure it was. Perhaps you means that Sun didn't let that stop them?

JUnit, for example, was using an assert() method and had to change it to assertTrue(). And lots of people had used "enum" as a local variable name for an Enumeration. That's legacy code, sure, but the point is they did create a number of compilation problems that had to be managed at the time. And they do still try to avoid creating new keywords for this reason, unless there's a good reason to do so. In this case, I don't think there was much benefit to adding "foreach" when "for" works perfectly well. Even Winston's new proposals above could probably have been handled with "for" and new syntax, without adding "foreach". I haven't thought that through super-carefully though.
 
Mike Simmons
Rancher
Posts: 4327
59
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Rob Spoor wrote:Sun (at the time) shot down this idea because of closures coming up.


Yeah, I think that makes sense as a reason not to introduce too many additional new syntaxes for things that lambdas will solve anyway. (Of course at the time Sun thought closures would be coming soon. Cough, cough...) The "foreach" loop made it in because it was short and simple, and handled the most common case by far. They also shot down various proposals to expose the Iterator for people who wanted to use remove() or any of the ListIterator methods. Too complex (in their opinion), with not enough code that would actually benefit from it.
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:

Rob Spoor wrote:Sun (at the time) shot down this idea because of closures coming up.


Yeah, I think that makes sense as a reason not to introduce too many additional new syntaxes for things that lambdas will solve anyway. (Of course at the time Sun thought closures would be coming soon. Cough, cough...) The "foreach" loop made it in because it was short and simple, and handled the most common case by far. They also shot down various proposals to expose the Iterator for people who wanted to use remove() or any of the ListIterator methods. Too complex (in their opinion), with not enough code that would actually benefit from it.


Yeah, you're probably right. I still think they could add my first idea in, maybe even without a new keyword, because it does conform to the general syntax for a 'for' loop (initialization - check - post-increment); the 'check' simply becomes the iteration.

Winston
 
Tony Docherty
Bartender
Posts: 3323
86
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:I said 'aside from [that]'.


Oops sorry chap, didn't read your post properly.

I do like your first suggestion. Needing an index whilst iterating over a collection is a fairly common requirement but I'm not convinced we need a new keyword to do it?
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tony Docherty wrote:Oops sorry chap, didn't read your post properly.


No probs. A ranter can't be bothered about paltry little issues like backward-compatibility.

but I'm not convinced we need a new keyword to do it?


Possibly not, but I do like the idea of assigning a name to this "new style" of loop (and it really is quite a departure from the old one). It also exists already in other languages, so it's hardly breaking new ground. And while I agree that new keywords should be rare, I think languages can hamstring themselves if they never allow them to happen (or the rules are so stringent as to make it almost impossible).

Winston

BTW: Thank you all for your contributions. I won't be holding my breath for any of my suggestions to come to pass; just felt like a rant.
 
Tony Docherty
Bartender
Posts: 3323
86
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Possibly not, but I do like the idea of assigning a name to this "new style" of loop (and it really is quite a departure from the old one). It also exists already in other languages, so it's hardly breaking new ground. And while I agree that new keywords should be rare, I think languages can hamstring themselves if they never allow them to happen


I guess it's a fine balance between the lack of backward compatibility caused by adding a new keyword and the potential confusion caused by overloading the meaning of an existing one.

Thank you all for your contributions. I won't be holding my breath for any of my suggestions to come to pass;


I agree it's unlikely to change anything, but if we never talk about these type of things then they will be guaranteed not to change. And besides that, the occasional rant is good for the soul.
 
Mike Simmons
Rancher
Posts: 4327
59
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Actually I expect these enhancements will be easily achievable under Java 8, using new methods rather than new keywords or new syntax. Lambdas will make it possible to define concise methods to handle the effects, and extension methods will allow them to add methods to existing interfaces with a default implementation. E.g. Iterable can have a foreach() method, or foreachWithIndex(). Map could get an eachEntry as well, but that doesn't really seem necessary, as entrySet().foreach() should handle that case well enough.

I shortened the last one by omitting the type, as that can be inferred by the compiler.

This stuff should be available next year. Or, of course, we could just use Groovy, Scala, or JRuby, where they're available now.
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:Actually I expect these enhancements will be easily achievable under Java 8, using new methods rather than new keywords or new syntax. Lambdas will make it possible to define concise methods to handle the effects, and extension methods will allow them to add methods to existing interfaces with a default implementation.


Good point. Be interesting to see what they come up with.

Winston
 
When you have exhausted all possibilities, remember this: you haven't - Edison. Tiny ad:
the value of filler advertising in 2021
https://coderanch.com/t/730886/filler-advertising
reply
    Bookmark Topic Watch Topic
  • New Topic