Oops, he did it again! Having started off with the disclaimer that he is working with the Groovy community, Charles Nutter has a
blog post that demonstrates how to do Groovy's coercion to a Map in JRuby.
Unfortunately, the irony in his post is that all he has done is demonstrate one of JRuby's shortcomings in terms of Java integration: it lacks built in coercion support. All of this is done whilst demonstrating only a small subset of what Groovy's as keyword is capable of.
The Ruby code demonstrated is as follows:
1. module InvokableHash
2. def as(java_ifc)
3. java_ifc.impl {|name, *args| self[name].call(*args)}
4. end
5. end
Which then can be used as a method like:
1. impl = {
2. :i => 10,
3. :hasNext => proc { impl[:i] > 0 },
4. :next => proc { impl[:i] -= 1 }
5. }
6. iter = impl.as java.util.Iterator
7. while (iter.hasNext)
8. puts iter.next
9. end
If you were to implement this in Groovy you could do:
1. Map.metaClass.as = { delegate.asType(it) }
However, in a further act of irony this code actually uses Groovy's built in coercion support and hence is in fact rather useless. All in one line of code!
What is even more amusing is his post conveniently skips over the fact that the
as keyword is a general purpose coercion mechanism for all types of coercion operations, not just maps. For example this is also possible:
1. { println 'foo' } as Runnable
And it can be extended by implementing the
asType method.
The most entertaining quote however is this one:
"Now if you ask the Groovy team, they'll make some claim like "it's all Java objects" or "Groovy integrates seamlessly with Java" but neither of those are entirely true."
Charles is trying hard to claim that JRuby's Java integration is no different to Groovy's. To those who want to try a little experiment have a go at this:
1) Write a plain JRuby/Groovy class
2) Write a Java class that creates a new instance of the JRuby/Groovy class and invokes a method on it
3) Set a break point on the Java class and step debug from the Java into the JRuby/Groovy class
4) Compile the sources and put them in a JAR
5) Put the JAR on the classpath of another app and write another Java class that references the JRuby/Groovy class
With Groovy and its joint compiler or IntelliJ IDEA's JetGroovy this is no problem, with JRuby you won't get passed step 2 without have to resort to introducing interfaces, creating dynamic proxies etc etc.
What the Groovy team says is this: Groovy has the same security model, the same debugger, the same profilers, the same object model, the same APIs, and close to the same syntax. For the Java developer its a no brainer.