Starting out on a chilly November morning, with just a Burger King
breakfast for company, I found myself checking in for the Eurostar
to Paris. I boarded the train, and found I had two hours of my
own time (a rare thing these days) and therefore decided to bring
some of my projects up to speed with the latest Groovy release
(JSR-04)
First off was my pet wiki server called biscuit, which was a
simple affair needing changes only to variables not initialized
with a type or the 'def' keyword. As I finish this task before
arriving at the channel tunnel I decided to sink my teeth into
a meatier topic, and look into providing tab completion for my
Groovy shell called grash. The excellent jline library hooks
for completion, so I quickly hook this up to the 'ls' function
in grash and feel great as I navigate my object tree using
the same nifty functionality I know in my favourite unix shells.
I then started bringing grash up to the latest Groovy release,
but after the initial 'def' updates, I quickly realise that
something else is afoot. It appears that providing user defined
commands and attaching them to objects has broken. A quick debugging
session shows that for some reason the GroovyClassLoader is being
told to load two versions of the reflector for the same script.
At this point I get a phone call from James Strachan, it appears
that he caught the train by the skin of his teeth, and after fighting
his way down the carriages we meetup, just as we pull into Paris.
As we stand in the queue for the taxis, James and myself discuss
the xbean project and how to best integrate Groovy closures into
Springs template callback mechanisms. In order to prevent writing
wrapper classes over the top of every spring template, James suggests
adding functionality to groovy to allow single method interfaces to
be automatically implemented by Closures, in much the same way as
Listeners are implementable by Closures today. As James pulls out
his laptop and starts showing me where these hooks would reside, I
can tell that this is going to be a good JSR meeting, and one which
would justify using two days of my own holiday and the excessive
eurostar fares which I paid for.
We arrive, after a hairy taxi ride around the 'Arc de Triumphe'
at the Sun offices in Paris. Guillaume excitedly takes us up
to the 'Jupiter' room on the third floor, where I finally get
to meet blackdrag, our debugger extraordinaire, and Dierk who
has been writing Groovy in Action. We are delighted to find that
Sun have provided an internet connection, and Guillaume has
already uploaded photos to flickr for the watching world to see.
Having missed the morning session due to our travel, we are quickly
brought up to speed. Finally we will get to talk about name resolution
and scoping. The topic for the first day appears to be name resolution,
with most of the discussion centring around how best to cope with vanilla
names.
After a lunch paid for, very kindly, by Dierk, the discussion
soon turns into a heated debate over the treatment of vanilla names.
class MyScript {
String toString(){
return "foo"
}
void run() {
myList.each{
// does this call MyScript.toString() or myList.toString() ?
println(toString())
}
}
I believe that... Tug argues the enclosing object instance should
listen for and consume names prior to the lexical scope. (i.e. above
example would call myList.toString())
James argues that the default should be lexically bound to the current
context (i.e. above example would call myScript.toString()), and if
the object instance was needed to be referred to that some form of syntax
could be constructed to allow this, e.g. $toString() would be a dynamic
name that could be interpreted differently.
At least, with my laptop pointing at the wiki, and up on the
projector, I ensure that the examples and minutes are being captured
in the wiki and not on the whiteboard.
We appear not to reach a resolution as Vincent Massol arrives to
bring us to the Chinese restaurant for the evening. We all potter
down to the Metro, Guillaume and tug have kindly arranged metro tickets
for us delegates too laden with bags, and soon we arrive across town.
There we meet Xwiki's Ludovic Dubost and Erwan Arzur and Benjamin Mestrallet from eXoPlatform.
A very entertaining evening ensues, with chatter ranging from XWiki through
to 'flaming drunk prawns', and we all end up at Ludovics apartment nearby,
where Erwan introduces us to a bottle of Calvados that he had stowed
away for such occasions. At about 12:30 we stumble back on the last
metro and finally check in to our sleepy hotel. I feel glad to find
a towel in the room, and settle down to a restless Parisian slumber.
(thanks so much to Bob at Codehaus for funding the room)
I awake 5 hours later to the sound of my Blackberry playing 'The
Entertainer', and discover the delights of hot chocolate for breakfast
(no sign of tea, I think coffee is more popular here). We stumble back
to the Sun offices, again Guillaume and tug have the metro sorted.
Day Two starts out more productive, with discussion about opening
up the DefaultGroovyMethods for the layman and we get some agreement about the
'use' keyword and my 'enhances' proposal. However the discussion soon
gets round to the topic of Builders (a.k.a. Markup) and again the name
resolution and scoping bear comes up to bite us again.
We have Tug and Guillaume firmly on the side of Builders being in charge
of everything defined within the markup delimiters. James argues that
markup is fundamentally broken and some kind of syntactic clue that
we are suddenly entering a different 'markup world' where normal
resolution and scoping doesn't apply. For some reason, that I cannot
fathom, Tug and Guillaume both seem vehemently opposed to any indication
in the code that we are in a Builder section. This includes both
the suggestion of a 'with' keyword or .{ notation to indicate to the
reader of the code that something different is about to occur.
String toString() {
return "foo"
}
swingBuilder.frame() {
panel() {
button(toString())
}
}
We were all fairly happy that the Builder could be responsible for
name resolution inside it's own block (e.g. the swingBuilder instance
would be responsible for how it treats toString() inside), but what
seemed to really be a sticking point was the important fact that
due to the dynamic nature of the name resolution/scoping within this
block, some visual clue to the reader of the program was necessary.
James argued for, and I agree that, the use of some kind of syntactic
indication was vital to ensure that the Groovy language was sane,
predictable and maintainable. The above example would look something
like this... (note the .{ syntax indicating a different lexical construct)
swingBuilder.frame().{
panel() {
button(toString())
}
}
or the even clearer...
with (swingBuilder.frame()) {
panel() {
button(toString())
}
}
Thus implying to any compiler, IDE, or human reader that the block
of code was not a true lexical closure, but some other construct
which was dynamic in it's very nature, and thus warnings, code completion
and everything else specification related did not apply, as the
responsibility would lie with the implementation of the builder.
I'm sad to report that no agreement was reached on this matter.
Not so much which syntax would be useful, but actually whether we
should have any syntax denoting the difference between a true
lexical Closure and one of these Builder blocks. The
historical reasons go back to Builder blocks looking just like
Closures, and I'm afraid this long standing mistake must be
removed from the language before any true progress can be made, as
no sensible specification rules can be applied while the dichotomy
exists.
I headed back to London with a very disappointed James Strachan,
the language which has some of the finest minds, and most exciting
ideas now faces a pivotal point in its life, and I'll do everything
I can to ensure that clarity over dynamism wins the day.
My many thanks go to Guillaume for the meeting arrangements, to
Sun for the facilities, to XWiki,eXoPlatform and Vincent Massol for the
Chinese, Dierk for the Lunch, and Bob/GoogleAds for the hotel room.