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 :-)

Tuesday, 18 December 2007

Closures - Comparing the core of BGGA, CICE and FCM

In this blog I'm going to compare the core of the three principle 'closure' proposals. This is particularly apt following the recent surge in interest after Josh Bloch's Javapolis talk.

Comparing 'closure' proposals

The three principle closure proposals are:

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

It is easy to get confused when evaluating these competing proposals. So much new syntax. So many new ideas. For this blog I'll summarise, and then deep dive into one area.

The first key point that I have been making recently is that closures is not 'all or nothing' - there are parts to the proposals that can be implemented separately. This table summarises the 5 basic parts in the proposals (I've split the last one into two rows):

  BGGA CICE+ARM FCM+JCA
Literals for reflection - - FCM member literals
References to methods - - FCM method references
One method callback classes BGGA closures CICE FCM inner methods
Function types BGGA function types - FCM method types
Library based Control Structure BGGA control invocation - JCA control abstraction
Language based Control Structure - ARM -

Of course a table like this doesn't begin to do justice to any of the three proposals. Or to express the possible combinations (for example, BGGA could add support for the first two rows easily). So, instead of talking generally, lets examine a key use case where all 'closure' proposals work.

One method callbacks

This issue in Java refers to the complexity and verbosity of writing an anonymous inner class with one method. These are typically used for callbacks - where the application code passes a piece of logic to a framework for it to be executed later in time. The classic example is the ActionListener:

  public void init() {
    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent ev) {
        // handle the event
      }
    });
  }

This registers a callback that will be called by the framework whenever the button is pressed. We notice that the code in the listener will typically be called long after the init() method has completed. While this is an example from swing, the same design appears all over Java code.

Some of the issues with this code are immediately obvious. Some are not.

  1. The declaration of the listener is very verbose. It takes a lot of code to define something that is relatively simple, and importantly, that makes it harder to read.
  2. Secondly, information is duplicated that could be inferred by the compiler. Its not very DRY.
  3. The scope of the code inside actionPerformed() is different to that of the init() method. The this keyword has a different meaning.
  4. Any variables and methods from the interface take preference to those available in init(). For example, toString(), with any number of parameters, will always refer to the inner class, not the class that init() is declared in. In other words, the illusion that the code in actionPerformed() has full access to the code visible in init() is just that - just an illusion.

The three closure proposals differ in how they tackle this problem area. BGGA introduces full closures. These eliminate all the problems above, but introduce new issues with the meaning of return. CICE introduces a shorthand way of creating an inner class. This solves the first issue, and some of the second, but does not solve issue 3 or 4. FCM introduces inner methods. These eliminate all the problems above, and add no new surprises.

  // BGGA
  public void init() {
    button.addActionListener({ActionEvent ev =>
      // handle the event
    });
  }
  // CICE
  public void init() {
    button.addActionListener(ActionListener(ActionEvent ev) {
      // handle the event
    });
  }
  // FCM
  public void init() {
    button.addActionListener(#(ActionEvent ev) {
      // handle the event
    });
  }

In this debate, it is easy to get carried away by syntax, and say that one of these might look 'prettier', 'more Java' or 'ugly'. Unfortunately, the syntax isn't that important - its the semantics that matter.

BGGA and FCM have semantics where this within the callback refers to the surrounding class, exactly as per code written directly in the init() method. This is emphasised by removing all signs of the inner class. The scope confusion of inner classes (issues 3 and 4 above) disappears (as this is 'lexically scoped').

CICE has semantics where this within the callback still refers to the inner class. Only you can't even see the inner class now, its really well hidden. This simply perpetuates the scope confusion of inner classes (issues 3 and 4 above) and gains us little other than less typing. In fact, as the inner class is more hidden, this might actually be more confusing than today.

BGGA also has semantics where a return within the callback will return from init(). This generally isn't what you want, as init() will be long gone when the button press occurs. (It should be noted that this feature is a major gain to the overall power of Java, but comes with a high complexity factor)

FCM and CICE have semantics where return within the callback returns from the callback, as in an inner class. This enables easy conversion of code from today's inner classes. (For FCM, the return is considered to be back to the # symbol, a simple rule to learn)

And here is my personal summary of this discussion:

  // BGGA
  public void init() {
    button.addActionListener({ActionEvent ev =>
      // return will return to init() - BAD for many (most) use cases
      // this means the same as within init() - GOOD and simple
    });
  }
  // CICE
  public void init() {
    button.addActionListener(ActionListener(ActionEvent ev) {
      // return will return to caller of the callback - GOOD for most use cases
      // this refers to the inner class of ActionListener - BAD and confusing
    });
  }
  // FCM
  public void init() {
    button.addActionListener(#(ActionEvent ev) {
      // return will return to caller of the callback - GOOD for most use cases
      // this means the same as within init() - GOOD and simple
    });
  }

Summary

This blog has evaluated just one part of the closures proposals. And this part could be implemented without any of the other parts if so desired. (BGGA would probably find it trickiest to break out just the concept discussed, but it could be done)

The point here is that there are real choices to be made here. The simplicity and understandability of Java must be maintained. But that doesn't mean standing still.

Once again, I'd suggest FCM has the right balance here, and that anyone interested should take a look. Perhaps the right new features for Java are method references and inner methods, and no more?

Opinions welcome as always :-)

Saturday, 15 December 2007

Voting on Java 7 language changes

This year at Javapolis I again looked after the whiteboards. In this post, I'll discuss the results.

Whiteboard results

The whiteboards play an important part at Javapolis in bringing people together to discuss ideas and future trends.

This year, I chose to focus the whiteboard debate around a number of specific topics. This was achieved by having votes on 10 language changes proposals, plus areas for new ideas for Spring, JSF, JavaEE and JavaSE. I'm going to discuss the language change votes here, as the photos of the other boards aren't available yet.

Language change votes

Before the conference started, there were a number of language change proposals floating about, initiated by Neal and Josh at Google. These were discussed in a late night BOF on Thursday, but this was backed up by the votes on the whiteboards.

The full results are available (with more detailed examples), but here is the summary.

The strongest support was for Improving Generics, String Switch and Multi-catch. Attendees were giving a clear 'yes' to these being in Java 7.

The strongest opposition was to Typedef (type aliasing) and Extension methods and chaining. Attendees were giving a clear 'no' to these being in Java 7.

There was some support for Better null handling (with a new operator) and Properties. The balance was slightly against, but not overwhelming.

There was positive support for Using [] to access lists and maps. The balance was definitely in favour, yet there was a large minority against. This was perhaps the most surprising vote. Unfortunately, it wasn't possible to find out why there were so many 'no' votes. My view, is that it is still worth pursuing this for Java 7.

Summary

Java being open source isn't going to be enough going forwards - it will also be necessary to provide an open community. Votes and direct feedback like this have a really positive effect, allowing Java's growth to be influenced by real developers and their problems.

The Javapolis Experience 2007

So, Javapolis is over for another year! Big thanks and congratulations to the Javapolis team for making it such an excellent conference.

This year I, personally, had more of a focus on the networking aspect of the conference - trying to take time to chat to many of the delegates and speakers. This is often where you make the interesting and surprising connections that will come in useful in the future.

Whiteboards

The whiteboards again played a really interesting part in getting people talking. This year, I left half the whiteboards as freeform, available for any comments. The other half were carefully organised to get a snapshot of opinions on specific topics.

These fell in three areas. Firstly, boards for collecting ideas for changes in Spring, JSF, J2EE and Java 7. Next up, was a board gathering information on how many people are using each application server, and each web framework.

Finally, about 10 language change proposals were described. Each of these was then offered with a vote - "Do you support this change" - Yes/No/Maybe. In the region of 150 votes were received for each of these proposals, so hopefully the results should be pretty representative. I'll discuss the results in my next blog post.

Closures

The other big topic of the conference was again closures. The first talk on the topic was a well-attended BOF from Neal Gafter discussing the current status of BGGA.

The second was a last minute change - something you'd never see at JavaOne! Josh Bloch gave a talk on 'The Closures Controversy', where he showed some examples of complexity added to the language with BGGA closures. He also showed the syntax proposals of CICE and ARM. This talk went down well with the audience, however it should be born in mind that Neal had no opportunity to respond directly to the points made.

Finally, in another last minute change, I gave a 15 minute quick talk on FCM+JCA closures. Despite being at lunchtime on the Friday, there was still a reasonable group in the audience, and the feedback I received personally was good.

There was also a whiteboard discussing closures, with a vote - No closures vs CICE vs BGGA. The vote was about 2 to 1 in favour of BGGA before Josh's talk, while it was about 50/50 afterwards. This suggests to me that opinions on the topic are not fixed and can be swayed by the last good presentation people see.

Looking forwards, the hope is to have all three proposals (CICE, BGGA and FCM) discussed on JavaPosse.

Summary

Javapolis really is a great conference. It is extremely well run, and has a really good feel. Stefan has said that he intends to keep it at Metropolis, Antwerp next year, so since it sold out this year, I suggest you get your tickets early next year!