Monday, February 25, 2008

Control Abstraction (version 2008-02-22)

Control Abstraction (version 2008-02-22)

In this post, I will describe new features of version 2008-02-22 of the compiler prototype. It can be downloaded from http://www.javac.info.

1. java.lang.Unreachable was renamed to java.lang.Nothing.

2. Annotation @Shared was added. It may annotate a variable bound in a closure. For example:

  static void doTwice({ => void } block) {
    block.invoke();
    block.invoke();
  }
  public static void main(String[] args) {
    @Shared int x = 10;
    doTwice({ => System.out.println(x++); });
  }
  

We should always annotate bound variables with this annotation because bound variables are very different from ordinary local variables.

3. Closures can use recursion. Now we can use the function variable within a closure that is used to initialize this variable.

  { int => int } sum = { int n => n == 1 ? 1 : n + sum.invoke(n - 1) };
  

4. Unrestricted closures were partially implemented. In an urestricted closure we can use the return, break, and continue statements. Unrestricted closures use ==> instead of =>.

  { int ==> int } neg = { int x ==> -x };
  

5. A method that accepts an unrestricted closure as the last argument can be called using the control invocation syntax:

  public static void simple({ ==> void } block) {
    block.invoke();
    block.invoke();
  }
  public static void main(String[] args) {
    simple() {
      System.out.println("vrr!");
    }
  }
  

The method may have more than one parameter:

  public static void profile(String s, { ==> void } block) {
    System.out.printf(">>> %s: %s%n", s, System.nanoTime());
    block.invoke();
    System.out.printf("<<< %s: %s%n", s, System.nanoTime());
  }
  public static void main(String[] args) {
    @Shared long f = 1;
    profile("factorial") {
      for (int i = 2; i <= 59; i++) {
        f *= i;
      }
    }
  }
  

The closure used as the last argument can have parameters. They are declared before arguments of the method and are separated from them by colon (although the syntax is similar to the enhanced for loop, the colon here has another meaning):

  public static void control(int x, { int ==> void } block) {
    block.invoke(x);
  }
  public static void main(String[] args) {
    // ordinary syntax
    control(1, { int i ==> System.out.println(i); });
    // control invocation syntax
    control(int i : 2) {
      System.out.println(i);
    }
  }
  

If the closure has more parameters, they are separated by comma:

  public static void controlTwo(int x, { int, int ==> void } block) {
    block.invoke(x, x + 1);
    block.invoke(x + 2, x);
  }
  public static void main(String[] args) {
    // closure parameters are separated by comma
    controlTwo(int i, int j : 2) {
      System.out.println(i * j);
    }
  }
  

This enables us to define new "control statements" without modifying the language. For example, we can add "statement" with that closes a given closeable at the end (the code is derived from the prototype sources):

  public static <T extends Closeable> void with(T t, { T ==> void } block) {
    try {
      block.invoke(t);
    } finally {
      try {
        t.close();
      } catch (IOException e) {
        // ignore exception
      }
    }
  }
  public static void main(String[] args) {
    // class MyCloseable implements Closeable
    with (MyCloseable in : new MyCloseable()) {
      //...
    }
  }
  

Why Java cannot remain simple? Do we need new control statements?
Many people like simplicity (I am one of them). But Java must evolve if we do not want it to become outdated. In addition, the hardware is changing and these changes will probably change programming languages used in software development. For information how the hardware is changing, I recommend the article The Free Lunch Is Over: A Fundamental Turn Toward Concurrency in Software. If you are curious how future programming languages may look like, have a look at x10 being developed at IBM. I also recommend the post Is Java dying?