Should we attempt to Java-ize the closure syntax for Groovy? At present, we use Ruby-style parameter lists for closures:
Apart from not being very Java-ish, this policy means the opening brace for the closure must appear on the same line as the statement with which it is associated.
One suggestion (from Sam, as I recall) is to use "new" as the closure marker:
This approach has the benefit of being reasonably inoffensive to Java programmers, as it uses Java keywords and parameter style. It does, however, call attention to how closures are implemented (ie. as anonymous classes), which may or may not be a good thing.
A similar alternative is to hold more closely to Ruby:
I think this reads better, as "do" indicates the purpose of the block, whereas "new" indicates how the magic is performed. The problem here is that we would be giving "do" an expression meaning, in addition to its existing statement meaning. "new" doesn't have this problem as it is already an expression. Further, optionalities may make the use of "do" for closures ambiguous with the use of "do" for loops. That said, I think the readability of "do" is worth the effort to make it work.
– Chris Poirier
At present, we have only one Closure to worry about. There has been some discussion, lately, of providing generators in the language. Aside from the procedural vs. declarative discussion we will have to have, there is also the question of how to present the syntax in the language.
A generator is, in some ways, a merging of a closure with an iterator – each call to the generator performs a single step in a series of operations and returns the value. As such, we will probably find it natural to use similar syntax for generators and closures, perhaps the only difference being the presence of a call to "yield()" in the body of the generator (I'm leaving the discussion of language-level backtracking support for another time). Note that this use of yeild() is very different from the use of yeild() in Ruby.
So, the question is: can we reuse closure syntax directly for generators (where "yield" is a keyword that causes the compiler to create a Generator instead of a Closure), or do we need some way for the user to specify the handling of any given block?
Possible example of block meaning selection:
– Chris Poirier
At present, there is no way (short of throwing an exception) to terminate a closure operation early. For instance, this does not work:
break and continue should work within closure bodies. continue is easy – it's just a jump to the end of the block. break is harder, as it has to coordinate with the caller. In Ruby, break exits the block with value "nil". The caller must check after each closure call to see if the value returned was "nil", and break itself, if necessary. A side effect is that you can't return "nil" from a block without terminating the calling structure. (As it happens, this is almost always acceptable.)
break could be implemented in two ways:
- the Ruby way (ie. the block return null, and the caller must check);
- with an exception that the caller must catch.
Option 1 is probably the better choice for performance, but does have the side effect of making null a special value. Option 2 makes it harder to forget to check for early exit.
– Chris Poirier