Jdk 1.5 extended for loop problem.

Discussion in 'Java' started by Carl Howells, Mar 3, 2004.

  1. Carl Howells

    Carl Howells Guest

    It seems that the extended for syntax added in Jdk 1.5 has one big issue
    making it more difficult to use than it should be.

    Consider the very useful new input class, java.util.Scanner. Scanner
    implements the Iterator<String> interface. That means that if I just
    want to tokenize a stream based on a fixed delimiter pattern, treating
    all the tokens as String objects, I can just treat the Scanner as an
    Iterater<String>, and be perfectly happy with the results.

    But I can't do that with the new extended for loop syntax. Here's an
    example of what I'd like to do, but currently can't:

    import java.util.*;

    public class Test
    {
    public static void main(String [] args) throws Exception
    {
    Scanner sc = Scanner.create(System.in);

    for (String s : sc)
    {
    System.out.printf("'%s'\n", s);
    }
    }
    }

    The problem is that the extended for syntax only allows instances of
    Iterable (And arrays... Have those been changed to implement Iterable,
    or does the syntax allow arrays as well as Iterable objects?) as the
    object to iterate over. This seems unnecessarily restrictive. This led
    to me writing some exceptionally stupid code just to be able to use the
    much cleaner for syntax:

    import java.util.*;

    public class Test
    {
    public static void main(String [] args) throws Exception
    {
    Scanner sc = Scanner.create(System.in);

    for (String s : new IteratorReturner<String>(sc))
    {
    System.out.printf("'%s'\n", s);
    }
    }

    static class IteratorReturner<E> implements Iterable<E>
    {
    private Iterator<E> it;

    IteratorReturner(Iterator<E> i)
    {
    it = i;
    }

    public Iterator<E> iterator()
    {
    return it;
    }
    }
    }

    I mean, that's just stupid. The extra class adds no semantic value. It
    doesn't make things clearer. It's just a stupid hack to make the types
    what the compiler wants.

    Consider how many API's return instances of Iterator or Enumeration,
    rather than a collection that implements Iterable. Why is having an
    adaptor class like the one needed above a cleaner solution than just
    allowing the extended for syntax to iterator over instances of Iterator
    and Enumeration?

    Does anyone else think that this is a big enough issue that it should be
    fixed? Is there anything about this in Sun's bug or RFE databases? I
    tried searching, but the search engine for those databases is severely
    limited.
    Carl Howells, Mar 3, 2004
    #1
    1. Advertising

  2. Carl Howells wrote:

    > Consider how many API's return instances of Iterator or Enumeration,
    > rather than a collection that implements Iterable. Why is having an
    > adaptor class like the one needed above a cleaner solution than just
    > allowing the extended for syntax to iterator over instances of Iterator
    > and Enumeration?
    >
    > Does anyone else think that this is a big enough issue that it should be
    > fixed?


    Definitely. It might even be better to forget about Iterable altogether.
    What if I want a ranged Iterator over a collection? Does that mean I
    can't use the new for loop?

    If the for loop accepted only an Iterator or Enumeration, the syntax
    would only be slightly less terse, but infinitely more flexible:

    for (T t : obj.iterator()) { }

    instead of the very limited, collection oriented:

    for (T t : collection) { }
    --
    Daniel Sjöblom
    Remove _NOSPAM to reply by mail
    =?ISO-8859-1?Q?Daniel_Sj=F6blom?=, Mar 3, 2004
    #2
    1. Advertising

  3. Carl Howells

    nos Guest

    "Carl Howells" <> wrote in message
    news:...
    > It seems that the extended for syntax added in Jdk 1.5 has one big issue
    > making it more difficult to use than it should be.
    >
    > Consider the very useful new input class, java.util.Scanner. Scanner
    > implements the Iterator<String> interface. That means that if I just
    > want to tokenize a stream based on a fixed delimiter pattern, treating
    > all the tokens as String objects, I can just treat the Scanner as an
    > Iterater<String>, and be perfectly happy with the results.
    >
    > But I can't do that with the new extended for loop syntax. Here's an
    > example of what I'd like to do, but currently can't:
    >
    > import java.util.*;
    >
    > public class Test
    > {
    > public static void main(String [] args) throws Exception
    > {
    > Scanner sc = Scanner.create(System.in);
    >
    > for (String s : sc)
    > {
    > System.out.printf("'%s'\n", s);
    > }
    > }
    > }
    >

    Don't you need a "new" in there somewhere (i b nube). Does it compile?

    > The problem is that the extended for syntax only allows instances of
    > Iterable (And arrays... Have those been changed to implement Iterable,
    > or does the syntax allow arrays as well as Iterable objects?) as the
    > object to iterate over. This seems unnecessarily restrictive. This led
    > to me writing some exceptionally stupid code just to be able to use the
    > much cleaner for syntax:
    >
    > import java.util.*;
    >
    > public class Test
    > {
    > public static void main(String [] args) throws Exception
    > {
    > Scanner sc = Scanner.create(System.in);
    >
    > for (String s : new IteratorReturner<String>(sc))
    > {
    > System.out.printf("'%s'\n", s);
    > }
    > }
    >
    > static class IteratorReturner<E> implements Iterable<E>
    > {
    > private Iterator<E> it;
    >
    > IteratorReturner(Iterator<E> i)
    > {
    > it = i;
    > }
    >
    > public Iterator<E> iterator()
    > {
    > return it;
    > }
    > }
    > }
    >
    > I mean, that's just stupid. The extra class adds no semantic value. It
    > doesn't make things clearer. It's just a stupid hack to make the types
    > what the compiler wants.
    >
    > Consider how many API's return instances of Iterator or Enumeration,
    > rather than a collection that implements Iterable. Why is having an
    > adaptor class like the one needed above a cleaner solution than just
    > allowing the extended for syntax to iterator over instances of Iterator
    > and Enumeration?
    >
    > Does anyone else think that this is a big enough issue that it should be
    > fixed? Is there anything about this in Sun's bug or RFE databases? I
    > tried searching, but the search engine for those databases is severely
    > limited.
    nos, Mar 3, 2004
    #3
  4. Carl Howells

    Carl Howells Guest

    nos wrote:
    > "Carl Howells" <> wrote in message
    >> import java.util.*;
    >>
    >> public class Test
    >> {
    >> public static void main(String [] args) throws Exception
    >> {
    >> Scanner sc = Scanner.create(System.in);
    >>
    >> for (String s : sc)
    >> {
    >> System.out.printf("'%s'\n", s);
    >> }
    >> }
    >> }
    >>

    >
    > Don't you need a "new" in there somewhere (i b nube). Does it compile?
    >


    Well, no, it doesn't compile, and that's the point of my post. But it
    fails to compile because sc isn't an instance of Iterable, not for any
    other reason.

    There are no other errors in that code. There's no use of the "new"
    keyword because I never instantiate an object directly by calling its
    constructor.
    Carl Howells, Mar 3, 2004
    #4
  5. Carl Howells

    Chris Uppal Guest

    Carl Howells wrote:

    > The problem is that the extended for syntax only allows instances of
    > Iterable (And arrays... Have those been changed to implement Iterable,
    > or does the syntax allow arrays as well as Iterable objects?) as the
    > object to iterate over. This seems unnecessarily restrictive.


    Now you mention it, it does indeed seem stupid.

    Does anyone know if the C# feature, from which it was presumably copied, has an
    analogous problem ?


    > Does anyone else think that this is a big enough issue that it should be
    > fixed?


    I think so. But it suggests that an even more important candidate for fixing
    is the review process itself. How did this one slip through the net ?

    (I'm not in general a fan of the new extensions -- although the loop thing
    seems pretty benign -- but if we're going to have them at all, then let's do
    them right.)

    -- chris
    Chris Uppal, Mar 4, 2004
    #5
  6. Chris Uppal wrote:
    > Carl Howells wrote:
    >
    >
    >>The problem is that the extended for syntax only allows instances of
    >>Iterable (And arrays... Have those been changed to implement Iterable,
    >>or does the syntax allow arrays as well as Iterable objects?) as the
    >>object to iterate over. This seems unnecessarily restrictive.

    >
    >
    > Now you mention it, it does indeed seem stupid.
    >
    > Does anyone know if the C# feature, from which it was presumably copied, has an
    > analogous problem ?


    I'm not sure why you think this feature was copied from C#. I've been
    using languages with some equivalent of foreach since way back when. I
    think QBasic had some sort of foreach, Perl does, Python does, TCL, Bash
    Lisp, Javascript ... pretty much every high-level language I can think of.

    I agree though that the Java one should work with Iterators and not
    require an Iterable object. I would say it should require an array, an
    object which implements Iterable, or an iterator. I would still like
    for there to be an Iterable interface so that I don't always have to add
    ".iterator()" for the common cases. But not accepting Iterator means I
    can't use the for loop with any existing classes which return Iterators
    yet don't implement Iterable, or classes which may have different
    methods which return different Iterators.
    Adam P. Jenkins, Mar 4, 2004
    #6
  7. Carl Howells

    Chris Uppal Guest

    Adam P. Jenkins wrote:

    > > Does anyone know if the C# feature, from which it was presumably
    > > copied, has an analogous problem ?

    >
    > I'm not sure why you think this feature was copied from C#. I've been
    > using languages with some equivalent of foreach since way back when.


    Oh, I'm not saying the *concept* of foreach originated in C# -- it clearly
    didn't. But I don't remember any calls for "foreach" to be added to Java
    until after C# had come out, and right from the start suggestions for adding it
    referred to the C# facility. Which is why I've assumed that the immediate
    ancestor of the new Java feature was C#. I certainly could be wrong; I'm not
    privy to the discussions that lead to its introduction.

    That aside, I'd still like to know if C# *does* suffer from an analogous
    problem.


    > I agree though that the Java one should work with Iterators and not
    > require an Iterable object. I would say it should require an array, an
    > object which implements Iterable, or an iterator. I would still like
    > for there to be an Iterable interface so that I don't always have to add
    > ".iterator()" for the common cases.


    I think (but it's too late now, I suppose) that it'd be better to handle just
    arrays and Iterator objects. Given the choices:

    1) Handle arrays and Iteratable only.
    2) Handle arrays and Iterator only.
    3) Handle arrays, Iterator *and* Iterable.

    (1) is -- as it seems everyone in this thread agrees -- inadequate.

    (2) is completely flexible, handles all iteration in a uniform manner (which I
    consider important), but at the slight cost of a little more typing in a common
    case.

    (3) has the advantage to requiring less typing on one common case, but at the
    cost of breaking the uniformity of use of iteration. Also potentially
    confusing. Also requires more complex specification since there's nothing to
    stop an object being both an Iterator and an Iterable.

    So, for me, (2) is to be preferred over (3).

    -- chris
    Chris Uppal, Mar 5, 2004
    #7
  8. Chris Uppal wrote:
    > Adam P. Jenkins wrote:
    >
    >
    >>>Does anyone know if the C# feature, from which it was presumably
    >>>copied, has an analogous problem ?

    >>
    >>I'm not sure why you think this feature was copied from C#. I've been
    >>using languages with some equivalent of foreach since way back when.

    >
    >
    > Oh, I'm not saying the *concept* of foreach originated in C# -- it clearly
    > didn't. But I don't remember any calls for "foreach" to be added to Java
    > until after C# had come out, and right from the start suggestions for adding it
    > referred to the C# facility. Which is why I've assumed that the immediate
    > ancestor of the new Java feature was C#. I certainly could be wrong; I'm not
    > privy to the discussions that lead to its introduction.
    >
    > That aside, I'd still like to know if C# *does* suffer from an analogous
    > problem.
    >
    >
    >
    >>I agree though that the Java one should work with Iterators and not
    >>require an Iterable object. I would say it should require an array, an
    >>object which implements Iterable, or an iterator. I would still like
    >>for there to be an Iterable interface so that I don't always have to add
    >>".iterator()" for the common cases.

    >
    >
    > I think (but it's too late now, I suppose) that it'd be better to handle just
    > arrays and Iterator objects. Given the choices:
    >
    > 1) Handle arrays and Iteratable only.
    > 2) Handle arrays and Iterator only.
    > 3) Handle arrays, Iterator *and* Iterable.
    >
    > (1) is -- as it seems everyone in this thread agrees -- inadequate.
    >
    > (2) is completely flexible, handles all iteration in a uniform manner (which I
    > consider important), but at the slight cost of a little more typing in a common
    > case.
    >
    > (3) has the advantage to requiring less typing on one common case, but at the
    > cost of breaking the uniformity of use of iteration. Also potentially
    > confusing. Also requires more complex specification since there's nothing to
    > stop an object being both an Iterator and an Iterable.
    >
    > So, for me, (2) is to be preferred over (3).


    The main point of the new for loop is for syntactic convenience, and (2)
    dilutes that too much for my taste. The case where I'm just calling
    iterator() on a collection is *by far* the most common case at least in
    my experience. I assume this is true for many others, which is why the
    feature ended up being designed the way it has. Still, there are enough
    other cases where I get an Iterator in some other way that I would like
    the for loop to work for those cases too. So (3) seems best to me.

    I must admit I didn't think of the problem of an Iterator being
    Iterable. I don't think it adds much complexity to the spec though:
    just declare that the Iterator interface takes precedence over Iterable
    (or vice versa.) It's such a borderline case that I don't think most
    programmers would even need to think about it.
    Adam P. Jenkins, Mar 5, 2004
    #8
  9. Daniel Sjöblom wrote:
    > If the for loop accepted only an Iterator or Enumeration, the syntax
    > would only be slightly less terse, but infinitely more flexible:
    >
    > for (T t : obj.iterator()) { }
    >
    > instead of the very limited, collection oriented:
    >
    > for (T t : collection) { }


    The colon could have been replaced by 'in' keyword, which would lead to
    more readable code:

    for (T t in collection) {}

    or

    for (T t in obj.iterator()) {}

    i'm not sure the last one would have been more readable ...
    =?ISO-8859-1?Q?Vahur_Sinij=E4rv?=, Mar 5, 2004
    #9
  10. Vahur Sinijärv wrote:
    > Daniel Sjöblom wrote:
    >
    >> If the for loop accepted only an Iterator or Enumeration, the syntax
    >> would only be slightly less terse, but infinitely more flexible:
    >>
    >> for (T t : obj.iterator()) { }
    >>
    >> instead of the very limited, collection oriented:
    >>
    >> for (T t : collection) { }

    >
    >
    > The colon could have been replaced by 'in' keyword, which would lead to
    > more readable code:
    >
    > for (T t in collection) {}
    >
    > or
    >
    > for (T t in obj.iterator()) {}
    >
    > i'm not sure the last one would have been more readable ...


    The rationale for using colon instead of a new keyword is backward
    compatibility. The current syntax doesn't break any existing code,
    whereas making 'in' be a keyword would break any existing code that used
    'in' as an identifier.
    Adam P. Jenkins, Mar 5, 2004
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Babar
    Replies:
    1
    Views:
    411
    Chris Smith
    May 20, 2004
  2. Thomas G. Marshall
    Replies:
    5
    Views:
    785
    Thomas G. Marshall
    Aug 6, 2004
  3. Ulf Meinhardt
    Replies:
    0
    Views:
    6,395
    Ulf Meinhardt
    Aug 10, 2006
  4. Jaggu
    Replies:
    3
    Views:
    964
    Nigel Wade
    Jan 8, 2007
  5. Isaac Won
    Replies:
    9
    Views:
    348
    Ulrich Eckhardt
    Mar 4, 2013
Loading...

Share This Page