The Source for Java Technology Collaboration
User: Password:



Rémi Forax's Blog

January 2008 Archives


Yet another closure proposal

Posted by forax on January 16, 2008 at 03:39 AM | Permalink | Comments (16)

Everybody comes with its own closure proposal, why not me :)

Unlike BGGA, CICE, or FCM (not entirely sure about FCM), i don't like the fact a closure is an instance of a class that implement a method. I prefer the John Rose's vision, closure are at runtime method handler on autonomous block of code.

There is another thing I don't like in the current BGGA proposal: its syntax of function type, {int,int=>int} is not enough Javaish for me. My proposal comes with a new way to declare a function type

I've separated my proposal in three parts:

  1. function type declaration
  2. how to use function type
  3. closure syntax
and because i'am lenient, i will only provide example and not a real spec.

Function types declaration

A function type is declared using the 'almost' keyword function.

// function types declaration
class Ops {

  // function are basically like typedef
  // top-level functions are illegal
  function <T> int comparator(T value1,T value2);

  // here function is not a real keyword, the compiler
  // recognize it as a keyword only in this construction
  function <E> void block(E element);

  // in the function below, E can be instantiated to any
  // object types or any primitive types,
  // it works because function are only declaration with no code. 

  // another function
  function <R> R task();
}

How to use function type

Function types are types so they can be used anywhere a type can be used except as bound of a type variable or type argument of a type variable.

// usage
import static Ops.*;

class Utils {
  // note: comparator<?> is illegal
  // (wildcard are prohibited for generics functions because
  // they are not needed).
  static <T> void sort(List<T> list,comparator<T> comparator) {
    ...
  }

  static <T> void forEach(Collection<T> c,block<T> block) {
    for(T t:c) {
      // invoke is a magic method that execute the block of code,
      // a special rule in the compiler is able to infer its
      // parameter type.
      block.invoke(t);
    }
  }
}

Closure syntax

Unlike function type syntax of BGGA, i like its closure syntax so basically my proposed closure syntax is identical. I have borrow method references from FCM even if we need to add a special lookup rule (because methods and fields are not in the same lookup space) for that in the compiler.
Like BGGA, my proposal include non local transfer and access to local variable (read and write) but only for closures and not for any anonymous classes, a closure is not an anonymous class. Like any proposal, my proposal allow interface conversion of function to interropt with legacy codes but only if closure use final local variable.
At last, return is not allowed in a closure to avoid stupid puzzlers but a replacement syntax exists.

// at calling site
class Main {
  static int f(Object o1,Object o2) {
    ...
  }

  void g(int value) {
    ...
  }

  public static void main(String[] args) {
    Ops.comparator<Object> c=Main.f;

    // using a primitive type here is legal,
    // it creates a block of code that call g()
    Ops.block<int> b=new Main().g; 

    List<String> l=Arrays.asList(args);
    Utils.sort(l,c); // ok contravariance

    // closure syntax, this syntax allow to specify the block of code
    Utils.sort(l,{Charsequence c1, CharSequence c2 =>
      c1.toString().compareTo(c1.toString());
    });

    // function to interface conversion
    java.util.Comparator<Object> javaUtilComparator=c;

    // it's roughly equivalent to
    final Ops.comparator<Object> tempc=c;
    java.util.Comparator<Object> javaUtilComparator=new java.util.Comparator<Object>() {
       public int compare(Object o1,Object o2) {
         return tempc.invoke(o1,o2);
       }
    };
    
    // closure to interface conversion
    java.util.Comparator<String> javaUtilComparator2={String s1, String s2 =>
      -s1.compareTo(s2);
    }); 
  }

Examples of non-local transfer and local variable mutation.

  // this is not allowed in contrast to BGGA.
  class NotAllowed implements Ops.block {
    ...
  }

  static int counter(Collection<Integer> c) {
    int count=0;
    // bloc of code (closure) can mutate local variable,
    // a function that returns an int is a subtype of a
    // function that returns void.
    Utils.forEach(c, {Integer i=>
      count+=i;
    });
    return count;
  }

  static boolean startsWith(Collection<String> c, String prefix) {
    // closure with non local tranfer,
    // moreover prefix doesn't need to be final
    // because this is not an interface conversion
    Utils.forEach(c, {String s=>
      if (s.startsWith(prefix) {
        return true; // doesn't compile ambiguous
        contains.return true; // ok
      } 
    });
  }
}

I wait your comments,
Rémi





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds