Thursday, 21 February 2008

Closures - Lightweight interfaces instead of Function types

Function types, or method types as FCM refers to them, are one of the most controversial features of closures. Is there an alternative that provides 80% of the power but in the style of Java?

Function/Method types

Function types allow the developer to define a type using just the signature, rather than a name. For example:

 // BGGA
 {String, Date => int}
 
 // FCM v0.5
 #(int(String, Date))

Apart from the different syntax, these are identical concepts in the two proposals as they currently stand. They both mean "a type that takes in two parameters - String and Date - and returns an int". This will be compiled to a dynamically generated single method interface as follows:

 public interface IOO<A, B> {
  int invoke(A a, B b);
 }

When instantiated, the generics A and B will be String and Date.

This is a complicated underlying mechanism. It is also one that can't be completely hidden from the developer, as the exception stack traces will show the auto-generated interface "IOO". This will certainly be a little unexpected at first. Update: Neal points out correctly that an interface name will not appear in the stacktrace!

A second complaint about function types is that there is no home for documentation. One of Java's key strengths is its documentation capabilities in the form of Javadoc. This is perhaps the unsung reason as to why Java became so popular in enterprises as a long-life, bet your company, language. Maintenance coders love that documentation. And everybody loves the ability to link to it within your IDE

So, why are we even considering function types? Well they allow APIs to be written that can take in any closure, simply defining it in terms of the input and output types. They also allow lightweight definition - there is no need to define the type before using it.

These are highly powerful features, and they lead towards functional programming idioms. But are these idioms completely in the style of Java?

Another option

Lets start from what we would write in Java today.

 public interface Convertor {
  int convert(String str, Date date);
 }

The advantage of this is that everyone knows and understands it. Its part of the lingua franca that is Java. Now lets examine what we could do with this.

Firstly, we need to remember that it is possible to define a class or interface such as this one within a method in Java today. The scope of such a class is the scope of the method. This will come in useful later.

So, lets examine what would happen if we start shortening the interface definition. For a function type equivalent, we know that there is only one method. As such, there isn't really any need for the braces:

 public interface Convertor int convert(String str, Date date);

Now, lets consider that for a function type equivalent, the method name is pre-defined as 'invoke'. As such, there is no need to include the method name:

 public interface Convertor int(String str, Date date);

Now, lets consider that for a function type equivalent, the parameter names are unimportant. As such, lets remove them (or maybe make them optional):

 public interface Convertor int(String, Date);

And that's it. I'm calling this a lightweight interface for now.

They represent a reasonable reduction of the code necessary to define a named single method interface. The syntax would be allowed anywhere an existing interface could be defined. This includes its own source file, nested in another class or interface, or locally scoped within a method. This is a longer example:

 // with function types (FCM syntax)
 public int process() {
  #(int(int, int)) add = #(int a, int b) {return a + b;};
  #(int(int, int)) mul = #(int a, int b) {return a * b;};
  return mul.invoke(add.invoke(2, 3), add.invoke(3, 4));
 }
 
 // with named lightweight interfaces - solution A
 interface Adder int(int,int);
 interface Multiplier int(int,int);
 public int process() {
  Adder add = #(int a, int b) {return a + b;};
  Multiplier mul = #(int a, int b) {return a * b;};
  return mul.invoke(add.invoke(2, 3), add.invoke(3, 4));
 }
 
 // with named lightweight interfaces - solution B
 public int process() {
  interface MathsCombiner int(int,int);
  MathsCombiner add = #(int a, int b) {return a + b;};
  MathsCombiner mul = #(int a, int b) {return a * b;};
  return mul.invoke(add.invoke(2, 3), add.invoke(3, 4));
 }

Solution A shows how you might define one lightweight interface for each operation. Solution B shows how you might define just one lightweight interface. It also shows that the lightweight interface could be define locally within the same method.

What we have gained is a name for the function type. It is now possible to write Javadoc for it and hyperlink to it in your IDE.

And it can be quickly and easily grasped as simply a shorthand way of defining a single method interface. In fact, you would be able to use this anywhere in your code as a normal single method interface, implementing it using a normal class, or extending it as required.

Its also possible to imagine IDE refactorings that would convert a lightweight interface to a full interface if you needed to add additional methods. Or to convert a single method interface to the lightweight definition.

Of course it would be possible to take this further by eliminating the name:

 // example showing what is possible, I'm not advocating this!
 public int process() {
  interface int(int,int) add = #(int a, int b) {return a + b;};
  interface int(int,int) mul = #(int a, int b) {return a * b;};
  return mul.invoke(add.invoke(2, 3), add.invoke(3, 4));
 }

However, the developer must now mentally parse both the lines "interface int(int,int)" to see if they are the same type. Previously, they could just see that they were both "MathsCombiner". As such, I prefer keeping the name, and requiring developers to take the extra step.

I see this as an example of where the style of Java differs from other more dynamic languages. In Java you always define your types up front. In more dynamic languages, you often just code the closure. As this concept requires defining types up front, I might suggest it is more in the Java style.

Final example

One final example is from my last blog post, this time in BGGA syntax:

 // Example functional programming style method using BGGA syntax
 public <T, U> {T => U} converter({=> T} a, {=> U} b, {T => U} c) {
   return {T t => a.invoke().equals(t) ? b.invoke() : c.invoke(t)};
 }
 
 // The same using lightweight interfaces
 interface Factory<C> C();
 interface Transformer<I, O> O(I);
 public <T, U> Transformer<T, U> converter(Factory<T> a, Factory<U> b, Transformer<T, U> c) {
   return {T t => a.invoke().equals(t) ? b.invoke() : c.invoke(t)};
 }

Personally, I find the latter to be much more readable, even though it involves more code. Both Factory and Transformer can be defined once, probably in the JDK or framework, and have associated documentation.

In addition, if I'd never seen the code before, I'd much prefer to be assigned to maintain the latter code with lightweight interfaces. Perhaps that is the key to Java's success - code that can be maintained. Write once. Read many times.

Thanks

Finally, I should note that some of the inspiration for this idea came from blogs and documents by Remi Forax and Casper Bang.

Summary

I've outlined an alternative to function types that keeps a key Java element - the type and its name. Lightweight interfaces are easy and quick to code if you don't want to document, but have the capacity to grow and be full members of the normal Java world if required.

I'd really love to hear opinions on this. It seems like a great way to balance the competing forces, but what do you think?

 

PS. Don't forget to vote for FCM at the java.net poll!

Tuesday, 19 February 2008

Evaluating BGGA closures

The current vote forces us all to ask what proposal is best for the future of Java. Personally, I don't find the BGGA proposal persuasive (in its current form). But exactly why is that?

Touchstone debate

The closures debate is really a touchstone for two other, much broader, debates.

The first "what is the vision for Java". There has been no single guiding vision for Java through its life, unlike other languages:

In the C# space, we have Anders. He clearly "owns" language, and acts as the benevolent dictator. Nothing goes into "his" language without his explicit and expressed OK. Other languages have similar personages in similar roles. Python has Guido. Perl has Larry. C++ has Bjarne. Ruby has Matz.

The impact of this lack of guiding vision is a sense that Java could be changed in any way. We really need some rules and a guiding Java architect.

The second touchstone debate is "can any language changes now be successfully implemented in Java". This is generally a reference to generics, where erasure and wildcards have often produced havoc. In the votes at Javapolis, 'improving generics' got the highest vote by far.

The result of implementing generics with erasure and wildcards has been a loss of confidence in Java language change. Many now oppose any and all change, however simple and isolated. This is unfortunate, and we must ensure that the next batch of language changes work without issues.

Despite this broader debates that surround closures, we must focus on the merits of the individual proposals.

Evaluating BGGA

BGGA would be a very powerful addition to Java. It contains features that I, as a senior developer, could make great use of should I choose to. It is also a well written and thought out proposal, and is the only proposal tackling some key areas, such as exception transparancy, in detail.

However, my basic issue with BGGA is that the resulting proposal doesn't feel like Java to me. Unfortunately, 'feel' is highly subjective, so perhaps we can rationalise this a little more.

Evaluating BGGA - Statements and Expressions

Firstly, BGGA introduces a completely new block exit strategy to Java - last-line-no-semicolon expressions. BGGA uses them for good reasons, but I believe that these are very alien to Java. So where do they come from? Well consider this piece of Java code, and its equivalent in Scala:

 // Java
 String str = null;
 if (someBooleanMethod()) {
  str = "TRUE";
 } else {
  str = "FALSE";
 }
 
 // Scala
 val str = if (someBooleanMethod()) {
  "TRUE"
 } else {
  "FALSE"
 }

There are two points to note. The first is that Scala does not use semicolons at the end of line. The second, and more important point is that the last-line-expression from either the if or the else clause is assigned to the variable str.

The fundamental language level difference going on here is that if in Java is a statement with no return value. In Scala, if is an expression, and the result from the blocks can be assigned to a variable if desired. More generally, we can say that Java is formed from statements and expressions, while in Scala everything can be an expression.

The result of this difference, is that in Scala it is perfectly natural for a closure to use the concept of last-line-no-semicolon to return from a closure block because that is the standard, basic language idiom. All blocks in Scala have the concept of last-line-no-semicolon expression return.

This is not the idiom in Java.

Java has statements and expressions as two different program elements. In my opinion, BGGA tries to force an expression only style into the middle of Java. The result is in a horrible mixture of styles.

Evaluating BGGA - Non local returns

A key reason for BGGA using an alternate block exit mechanism is to meet Tennant's Correspondance Principle. The choices made allow BGGA to continue using return to mean 'return from the enclosing method' whilst within a closure.

There is a problem with using return in this way however. Like all the proposals, you can take a BGGA closure, assign it to a variable and store it for later use. But, if that closure contains a return statement, it can only be successfully invoked while the enclosing method still exists on the stack.

 public class Example {
  ActionListener buttonPressed = null;
  public void init() {
   buttonPressed = {ActionEvent ev => 
     callDatabase();
     if (isWeekend() {
      queueRequest();
      return;
     }
     processRequest();
   };
  }
 }

In this example, the init() method will be called at program startup and create the listener. The listener will then be called later when a button is pressed. The processing will call the database, check if it is weekend and then queue the request. It will then try to return from the init() method.

This obviously can't happen, as the init() method is long since completed. The result is a NonLocalTransferException - an unusual exception which tries to indicate to the developer that they made a coding error.

But this is a runtime exception.

It is entirely possible that this code could get into production like this. We really need to ask ourselves if we want to change the Java programming language such that we introduce new runtime exceptions that can be easily coded by accident.

As it happens, the BGGA specification includes a mechanism to avoid this, allowing the problem to be caught at compile time. Their solution is to add a marker interface RestrictedFunction to those interfaces where this might be a problem. ActionListener would be one such interface (hence the example above would not compile - other examples would though).

This is a horrible solution however, and doesn't really work. Firstly, the name RestrictedFunction and it being a marker interface are two design smells. Secondly, this actually prevents the caller from using ActionListener with return if they actually want to do so (within the same enclosing method).

The one final clue about non local returns is the difficulty in implementing them. They have to be implemented using the underlying exception mechanism. While this won't have any performance implications, and won't be visible to developers, it is another measure of the complexity of the problem.

In my opinion, allowing non local returns in this way will cause nothing but trouble in Java. Developers are human, and will easily make the mistake of using return when they shouldn't. The compiler will catch some cases, with RestrictedFunction, but not others, which will act as a further level of confusion.

Evaluating BGGA - Functional programming

Java has always laid claim to be an OO language. In many ways, this has often been a dubious claim, especially with static methods and fields. Java has never been thought of as a functional programming langauge however.

BGGA introduces function types as a key component. These introduce a considerable extra level of complexity in the type system.

A key point is that at the lowest compiler level, function types are no different to ordinary, one method, interfaces. However, this similarity is misleading, as at the developer level they are completely different. They look nothing like normal interfaces, which have a name and javadoc, and they are dynamically generated.

Moreover, function types can be used to build up complex higher-order function methods. These might take in a function type parameter or two, often using generics, and perhaps returning another function type. This can lead to some very complicated method signatures and code.

 public <T, U> {T => U} converter({=> T} a, {=> U} b, {T => U} c) {
   return {T t => a.invoke().equals(t) ? b.invoke() : c.invoke(t)};
 }

It shoud be noted that FCM also includes function types, which are named method types. However, both Stefan and myself struggle with the usability of them, and they may be removed from a future version of FCM. It is possible to have FCM inner methods, method references and method literals without the need for method types.

Function types have their uses, however I am yet to be entirely convinced that the complexity is justified in Java. Certainly, they look very alien to Java today, and they enable code which is decidedly hard to read.

Evaluating BGGA - Syntax

The syntax is the least important reason for disliking BGGA, as it can be altered. Nevertheless, I should show an example of hard to read syntax.

 int y = 6;
 {int => boolean} a = {int x => x <= y};
 {int => boolean} b = {int x => x >= y};
 boolean c = a.invoke(3) && b.invoke(7);

Following =>, <= and >= can get very confusing. It is also a syntax structure for parameters that is alien to Java.

Summary

As co-author of the FCM proposal it is only natural that I should want to take issue with aspects of competitor proposals. However, I do so for one reason, and that is to ensure that the changes included in Java 7 really are the right ones. Personally, I believe that BGGA attempts something - full closures - that simply isn't valid or appropriate for Java.

It remains my view that the FCM proposal, with the optional JCA extension, provides a similar feature set but in a more natural, safe, Java style. If you've read the proposals and are convinced, then please vote for FCM at java.net.

Opinions welcome as always :-)

References

For reference, here are the links to all the proposals if you want to read more:

  • BGGA - full closures for Java
  • CICE - simplified inner classes (with the related ARM proposal)
  • FCM - first class methods (with the related JCA proposal)

Sunday, 17 February 2008

Vote for FCM!

Java.net is currently running a poll on closures, to get a feel for the strength of support for each proposal. Obviously, this poll has no power, but it is useful to see at a high level what the communities opinion is.

Personally, I'm really pleased with the level of support FCM has had in the vote so far, on this blog and privately. Now I'd like to encourage you, if you so desire, to vote and support FCM. Thanks!

Update: If you want to compare the three proposals, please take a look at my previous comparison articles - one method callbacks, control structures and type inference.

Monday, 28 January 2008

Java 7 - Multi-line String literals

One of the most common features in other programming languages is the multi-line String literal. Would it be possible to add this to Java?

Update, 2011-10-31, Just wanted to note that multi-line strings are not in Java 7, nor are they likely to be in Java 8. This blog post is still useful to understand some of the difficulties that would have to be tackled if they were to be included in future.

Update, 2018-01-28: This is now being considered for addition to Java, read more here.

Multi-line String literals

In Java today there is only one form of string literal, supplied in double quotes. Within those double quotes, certain characters have to be escaped.

 String basic = "Hello";
 String three = "This string\nspans three\nlines";
 String welcome = "Hello, My name is \"Stephen\", Hi!";

The first of these two examples is not complex, and would not make use of a multi-line String literal. The other two might be more readable with such a literal.

The standard for defining a multi-line String literal in both Scala and Groovy is three double quotes. This also seems like a sensible choice for Java:

  String three = """This string
spans three
lines""";

This is potentially much more readable, especially with large blocks of text. This form of literal would also avoid the need for escaping:

 String welcome = """Hello, My name is "Stephen", Hi!""";

Note that we no longer need to escape the double quotes. This would be especially useful for regular expressions.

Bear in mind that multi-line String literals are fundamentally no different to normal String literals on the key point of the object created. Both would create java.lang.String objects.

Issues

The first issue is the multi-line arrangement. Since all text within the multi-line literal is included, all lines except the first must begin from column zero. This will look odd in a piece of well-formatted Java code:

  // what a naive multi-line literal forces us to write
  public class MyClass {
    public void doStuff() {
      String three = """This string
spans three
lines""";
      System.out.println(three);
    }
  }
  
  // what we'd like to write
  public class MyClass {
    public void doStuff() {
      String three = """This string
                        spans three
                        lines""";
      System.out.println(three);
    }
  }

One possible solution is to provide a method on String that strips all whitespace after each newline. This could be called directly after the literal. Unfortunately this approach loses some efficiency as the string must be trimmed each time:

  // option with trimNewline()
  public class MyClass {
    public void doStuff() {
      String three = """This string
                        spans three
                        lines""".trimNewLine();
      System.out.println(three);
    }
  }

Another, perhaps better, solution might be to have a syntax variation. If the opening triple quote is followed immediately by a newline, then the position of the first non-space character on the next line represents the column to begin the literal at. (The first newline would not be included in this form of the literal.) Only the space character would be permitted in earlier columns until the end of the literal. This would allow for natural formatting of this kind of string:

  // option with columns determined by first line
  public class MyClass {
    public void doStuff() {
      String three = """
              This string
              spans three
              lines""";
      System.out.println(three);
    }
  }

One final tricky issue is handling a string containing the triple double quote. The answer is probably to ignore this situation (Scala does this). It is going to be very rare, and it can be worked around using string concatenation.

Summary

Multi-line String literals should be a relatively easy addition to Java (anyone fancy adding it to Kijaro?). The main benefits would be avoiding escaping in regular expressions, and pasting in large blocks of text from other sources.

Overall, I think they would be a valuable addition to Java. But have I missed any obvious issues? Are there any other syntax options that should be considered? Opinions welcome as always :-)

Friday, 25 January 2008

Closures - Comparing closure type inference

In this blog I'm going to compare the three principle 'closure' proposals based on how they infer types. This follows my previous comparison blogs.

Here are the links to the proposals if you want to read more:

  • BGGA - full closures for Java
  • CICE - simplified inner classes (with the related ARM proposal)
  • FCM - first class methods (with the related JCA proposal)

Type inference

Type inference is where the compiler works out the type of a given expression without the programmer needing to explicitly state the type. For example:

 String str = "Hello";

In the above, the type of str is known to be a String because it is stated by the developer. However, there is no actual need for the developer to manually state the type of 'String'. Instead, the compiler (not the Java 1.6 compiler) could work it out itself by infering the type from the literal "Hello" - hence 'type inference'.

Closures

Lets consider how the closures proposals allow some limited type inference in Java. Consider this single method interface:

 public interface PairMatcher<T,U> {
   boolean matches(T arg1, U arg2);
 }

The purpose of the interface is to allow developers to write a callback that takes two arguments and returns true if they 'match' some criteria that is important to the developer. Here is an example of such a framework method, that searches through two lists and returns the matched entry:

 public T find(List<T> list1, List<U> list2, PairMatcher<T,U> matcher) {
   for (T t : list1) {
     for (U u : list2) {
       if (matcher.matches(t, u)) {
         return t;
       }
     }
   }
   return null;
 }

And here is how calling this code looks today using an inner class:

 List<String> stringList = ...
 List<Integer> integerList = ...
 String str = find(stringList, integerList, new PairMatcher<String,Integer>() {
   public boolean matches(String str, Integer val) {
     return (str != null && str.length() > 0 && val != null && val > 10);
   }
 });

BGGA

With BGGA, the code can be shortened to use use a closure:

 List<String> stringList = ...
 List<Integer> integerList = ...
 String str = find(stringList, integerList, {String str, Integer val =>
   (str != null && str.length() > 0 && val != null && val > 10)
 });

Obviously the code is shorter. But it is important to understand what has occurred. The type PairMatcher, and its generic arguments, have been inferred. This happened as the BGGA compiler identified which method was being called. In order to call the method, a 'closure conversion' occurred, which changed the closure to a PairMatcher with the correct generics.

So, not only is the type inferred, but the generic arguments are as well.

FCM

FCM can be used, like BGGA, to shorten the original:

 List<String> stringList = ...
 List<Integer> integerList = ...
 String str = find(stringList, integerList, #(String str, Integer val) {
   return (str != null && str.length() > 0 && val != null && val > 10);
 });

Exactly the same conversion and type inference is occurring as in BGGA. Thus, for this scenario of type inference, FCM and BGGA have the same power, just different syntax.

CICE

CICE also provides a means to shorten the original:

 List<String> stringList = ...
 List<Integer> integerList = ...
 String str = find(stringList, integerList, PairMatcher<String,Integer>(String str, Integer val) {
   return (str != null && str.length() > 0 && val != null && val > 10);
 });

I hope that this example makes it clear that there is no type inference here as there was in FCM and BGGA. Instead, the developer still has to type the interface name and, more significantly, the generic arguments.

While just typing the interface name might be regarded as a documentation benefit by some, I would suggest that it is very hard to justify the retyping of the generic arguments. Clearly, for this scenario of type inference, CICE has less power than FCM and BGGA.

Comparison

Both BGGA and FCM support the same style of type inference for the single method interface and it's generic arguments. CICE does not, and with generics that results in quite a verbose result for the developer to type.

Summary

There are two basic approaches here - infer or be explicit. My view is that this is an area where inference is really needed. With CICE, I find it hard to see how this is really much of a gain over an inner class.

Opinions welcome as always :-)

Monday, 7 January 2008

Java 7 - Checked exception library change

Personally, I don't like checked exceptions. But why? And can we do anything about it?

Checked exceptions

Its fairly well known that checked exceptions were a kind of experiment in Java. Its also fairly well known that other newer languages are not choosing to follow. The basic reason is that as a language feature they haven't met their goal.

The expectation was that checked exceptions would improve exception handling quality. The reality is that they haven't:

  public void process() {
    try {
      callSomeExceptionThrowingMethod();
    } catch (Exception ex) {
      // ignore
    }
  }

I hope that most of us recognise this as an anti-pattern (in most cases). Rather than discuss this much longer, I'll point everyone at Joshua Gertzen's blog.

His blog reminded me of a possible library change (yes library, not language!) I'd thought of that might help. At least it is something I'd like opinions on:

  public void process() {
    try {
      callSomeExceptionThrowingMethod();
    } catch (Exception ex) {
      ex.rethrowUnchecked();
    }
  }

So, what does 'rethrowUnchecked()' on Exception do? Well it would rethrow the exception, but ignoring the checked exception status of the exception.

  public void rethrowUnchecked() {
    Unsafe.getUnsafe().throwException(this);
    return null;
  }

This all works with Java today. There is no language change, just an alternative view of an existing capability.

So, why would this be useful? Well, I suggest that this could be a better way to handle annoying checked exceptions that we don't really care about. In particular, I believe that it would be easier to understand the exception trace, as it wouldn't consist of lots of nested exceptions - no more 'throw new RuntimeException(ex)'.

Summary

I'm not convinced of the benefits of this one yet. It seems neat, but does it really benefit us, as we still have to write the catch block? Perhaps it is more suited to a language change? Opinions welcome as always :-)

Tuesday, 1 January 2008

Closures - Comparing control structures of BGGA, ARM and JCA

In this blog I'm going to compare the second major part of the three principle 'closure' proposals - control structures. This follows my previous blog where I compared one method callbacks.

Here are the links to the proposals if you want to read more:

  • BGGA - full closures for Java
  • CICE - simplified inner classes (with the related ARM proposal)
  • FCM - first class methods (with the related JCA proposal)

Comparing 'closure' 'control structure' proposals

Firstly, what do we mean by control structure problems? Well, there are three classic use cases:

 // resource management
 try {
   // open resource
   // use resource
 } finally {
   // close resource
 }

 // locking
 try {
   // lock
   // process within the lock
 } finally {
   // unlock
 }

 // looping around a map
 for (Map.Entry<String,Integer> entry : map.entrySet()) {
   String key = entry.getKey();
   Integer value = entry.getValue();
   // process map
 }

Each of the three principle closure proposals provide a solution to some or all of these issues.

BGGA

BGGA treats control structures as simply an alternative way to invoke a method. This allows any developer to write control structures, something referred to as library-defined control structures.

Thus, with BGGA, you can write a method to manage a lock. This can be called in two ways - either by passing the closure as a parameter, or by following the method call by the block.

 // library defined control structure
 public void withLock(Lock lock, {=>void} block) {
   lock.lock();
   try {
     block.invoke();
   } finally {
     lock.unlock();
   }
 }

 // call using closure as parameter
 withLock(lock, {=>
   // process within the lock
 });

 // call using control invocation syntax
 withLock(lock) {
   // process within the lock
 }

Whichever style is used, the meaning of return and this is the same. The return keyword will return from the lexically enclosing method, which is entirely sensible for control invocation. The this keyword also refers to the lexically enclosing class.

CICE/ARM

CICE does not support control structures. Instead, this area is covered by the ARM proposal.

The basic idea behind the ARM proposal is that control structures should only be added by language designers, and should not be able to be added to libraries.

The ARM proposal itself is merely an outline proposal and does not have detail. However, Josh Bloch has indicated that he would see ARM tackling specific issues, notably resource management and locking.

 // resource management
 try (BufferedReader r = new BufferedReader(new FileReader(file))) {
   // process resource
 }

 // locking
 protected(lock) {
   // process within the lock
 }

As this is a language change, it has to wait until a new version of Java is released. In addition, the meaning of return and this is naturally as per any other language defined control statement, such as a normal try block.

FCM/JCA

FCM does not support control structures. Instead, this area is covered by the JCA proposal.

The basic idea behind the JCA proposal is that control structures can be added by anyone, but that they should clearly be separated from the one method callback cases. The aim of the separation is to send a message to developers - adding a control structure in a library is something that should be undertaken with care.

 // library defined control structure
 public void withLock(#(void()) block : Lock lock) {
   lock.lock();
   try {
     block.invoke();
   } finally {
     lock.unlock();
   }
 }

 // call
 withLock(lock) {
   // process within the lock
 }

It should be noted that this is similar to the BGGA design. The calling code is identical to BGGA's control invocation syntax. However, you cannot pass the block of code as a parameter to the method as you can in BGGA - there is only one calling syntax.

The library defined control structure is very different however. In JCA, the library method has a special syntax with the block before the colon, and the input parameters after the colon. This matches the callers syntax, and clearly indicates that this is a 'special' kind of method.

Again, the meaning of return and this is lexically scoped, as with BGGA and ARM.

Comparison

Each of the three approaches has merits.

BGGA provides a full-featured approach, where a closure is treated as it would be in most other languages. Control structures can be written in libraries, and the control invocation syntax is just sugar for a normal method call.

ARM provides a use-case based approach. It solves specific problems with specific language changes. This doesn't allow ordinary developers to add control structures, but does provide valuable, reliable, enhancements.

JCA sits between BGGA and ARM, but because it allows library-defined control structures it is closer to BGGA. It differs from BGGA in that it treats control structures as effectively a separate language change to one method callbacks. By doing this, and with specific syntax, it aims to slightly discourage the extensive use of library-defined control structures.

Summary

There are two basic approaches to control structures - let language designers write them, eg. ARM, or let anyone write them, eg. BGGA or JCA. The BGGA and JCA proposals differ mainly on syntax, where JCA is using the syntax to warn against excessive or inappropriate use of control structures.

My own view is that everyone should have the right to write control structures, and that it will allow the Java language to keep fresh without lots of pressure on Sun to add new language features.

However, the right to add control structures comes with responsibilities. If everyone writes control structures all the time, then the resulting code might look more like a dialect of Java than Java itself. That is why I favour JCA, which aims through syntax and documentation to encourage serious consideration before writing a control structure.

Opinions welcome as always :-)