Calling Scala Collection methods in Groovy

by 2/27/2012 03:29:00 PM 0 comments
As you can tell by some of my other blog posts, I'm a fan of Java, Scala, and Groovy. I really like to use Scala as much as possible, but the Scala REPL can be a little quirky at times. On the other hand, Groovy's REPL is like a trusted tool, it always seems to work when I need it. Today I tried doing some ad hoc things in a Scala shell involving JPA and Guice. Unfortunatly, Scala was having none of it and the scala REPL was giving me fun messages like:

javax.persistence.PersistenceException: No Persistence provider for EntityManager named dsg-jpa

Now, without diving into the 'why' of this annoyance, I changed over to my handy Groovy shell (NOTE: I almost always ship both a Groovy and a Scala console in my applications so that I can use either as needed). Voila, that annoying exception disappeared. However, now I found myself working in Groovy-land but calling code that returned Scala collections. The good thing is that the semantics working with Groovy and Scala collections are similar:

// --- Groovy
// each(grooy.lang.Closure)
javaList.each { item -> println(item) }

// --- Scala
// foreach(scala.Function1)
scalaList.foreach { item => println(item) }

However,  on the one hand, being a Scala collection and not a java collection there's no each method to be called. If you try to use it in a Groovy fashion you'll get the following:

// In Groovy Shell
scalaList.each { item -> println(item) }
ERROR java.lang.ClassCastException:
scala.collection.JavaConversions$JIteratorWrapper cannot be cast to java.util.Iterator

On the other hand, if you call it using Scala's foreach you'll get the following:

// In Groovy Shell
scalaList.foreach { item -> println(item) }
ERROR groovy.lang.MissingMethodException:
No signature of method: scala.collection.JavaConversions$JListWrapper.foreach() is
 applicable for argument types: (groovysh_evaluate$_run_closure1) values: 
[groovysh_evaluate$_run_closure1@46aea8cf]
Possible solutions: each(groovy.lang.Closure)

// Not very helpful is it

Fortunately, Groovy allows us to very easily cast a groovy.lang.Closure to a Scala function, in this case a scala.Function1. So the following will work:
// In Groovy Shell
scalaList.foreach({ item -> println(item) } as scala.Function1)

Brian Schlining

Developer

Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.

0 comments: