For-each loop control

Stephen Colebourne

Version 0.1

I. Problem

The Java language, since version 5, has supported an enhanced for-each loop. This has proved to be a very popular feature, and greatly enhances the readability of many loops.

Unfortunately, the enhanced for-each loop does not provide the ability to access the loop index, to remove items, to change items or determine if this is the first or last loop iteration.

These missing features are frequently a problem whilst coding. A typical editing session might begin by writing a for-each loop. Only when most of the way through writing the loop do you realise that you need to remove an item from the collection, or access the index. At that point, the developer is required to go back and completely rewrite the loop syntax to the older, less clear, more error prone version.

This proposal is to extend the enhanced for-each loop facility to provide access to control information. For example:

  List<String> list = new ArrayList<String>();

 

  for (String str : list : it) {

    System.out.println("Item:" + str + ", Index:" + it.index());

    if (str == null) {

      it.remove();

    }

  }

There are various ways to achieve this in current code, such as:

  List<String> list = new ArrayList<String>();

 

  int i = 0;

  for (Iterator<String> it = list.iterator(); it.hasNext(); i++) {

    String str = it.next();

    System.out.println("Item:" + str + ", Index:" + i);

    if (str == null) {

      it.remove();

    }

  }

Thus, this change can be seen to be relatively simple syntax sugar for existing code.

II. For-each loop control

This proposal extends the existing for-each loop to provide control structure access.

The proposed syntax is [1]:

     EnhancedForStatement:

         for ( VariableModifiersopt Type Identifier : Expression) Statement

         for ( VariableModifiersopt Type Identifier : Expression : Ident) Statement

The additional identifier, known as the iteration control variable, is a valid identifier in the variable namespace. No explicit type is specified.

The scope of the iteration control variable is the contained Statement

The iteration control variable will support a number of 'methods'. The exact mechanism for this support is discussed in section III.

III. Issues

The proposal needs a means to define the available 'methods' on the iteration control variable. Two options are considered here:

a) Single interface

This approach would involve writing a single interface with all the possible control methods for arrays, iterables, collections and lists. This would be along the lines of the following:

public interface IterableControl<E> {

  E set(E newValue);

  E remove();

  int index();

  int originalIndex();

  boolean isFirst();

  boolean isLast();

  int size();

}

The implementation would be provided by the compiler. Arrays would not support remove(), while set() would only be supported on lists. It would however not be a compile error to call the unsupported methods.

b) Direct syntax - no interface

This approach would involve there being no explicit interface. The compiler would implement the various methods in a way that the developer might have done. Thus, the compiler would implement index() and isFirst() by generating and incrementing a local int variable.

Option (b) is potentially more complex than option (a) for the compiler writer, however it appears to be a lot cleaner for the developer. In particular, only those functions that make sense will compile, and each function will be written in the most optimal way, exactly as a developer would have written it.

The main downside of option (b) is that it is effectively all language-based rather than library, thus it would all have to be specified in the JLS [1]. Put another way, the question is whether the iterator control variable is a regular Java object with a type, or a contextual keyword-variable. If it is the latter, then it would be unassignable to Object and the developer would be unable to pass it to other methods.

A linked document to this one is Enhanced for-each for Maps [4]. Were that proposal to be adopted, then this proposal would need to be extended to support map access methods on the iterator control variable.

IV. Alternatives

The main alternate proposal is the control invocation syntax of BGGA [2] or FCM+JCA [3] closures. The advantage of this proposal is that it is simple and self contained, being just a logical extension of the Java 5 changes, whereas closures are a much larger change. This proposal also avoids the need for importing static methods, or special casing continue/break using exceptions.

V. References

  1. The Java Language Specification, Third Editionhttp://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html
  2. G. Bracha, N. Gafter, J. Gosling, P. von der Ahé: "Closures for the Java Programming Language  (v0.5)"http://www.javac.info
  3. Java Control Abstraction - Java Control Abstraction
  4. For-each loop for Maps - For-each loop for Maps