Groovy and Java Callbacks / Lambdas (Closures with a type) - groovy

This is a callback I have in Java (future is a Mongo's SingleFutureResult):
future.register(new SingleResultCallback<ArrayList<Document>>() {
#Override
void onResult(ArrayList<Document> documents, MongoException e) {
//do something
}
})
With Java 8 I can use Lambdas to make it look like this:
future.register((documents, e) -> {
//do something
});
Neat. However, I would like to call that Java method within a Groovy class. I know Groovy does currently not support jdk8 lambda's syntax, but the docs always stress that they have closures instead. If I try to use a closure in such a case it fails, as the closure is of type Closure, and not of type SingleResultCallback. Is there a way to have something like a closure with a different type? Is there any other way to make this work in a nice way? I know I can use the first solution, but that looks pretty weird within a groovy class.

Use Groovy's closure syntax:
future.register( { documents, e ->
//do something
});
If there is ambiguity in a register method overload, it might need as SingleResultCallback after the closure declaration:
future.register { documents, e -> } as SingleResultCallback
This is an ambiguity scenario:
interface SingleResultCallback<T> {
def onResult(T result)
}
interface Callback { def onResult(obj) }
class Future {
void register(SingleResultCallback s) {
println "registered: ${s.onResult(10)}"
}
void register (Callback r) {
println "runnable=${r.onResult()}"
}
}
new Future().register { it ** 2 }
Which fails with:
Caught: groovy.lang.GroovyRuntimeException:
Ambiguous method overloading for method Future#register.
Cannot resolve which method to invoke for [class Sam$_run_closure1] due
to overlapping prototypes between:
[interface Callback]
[interface SingleResultCallback]
And if SingleResultCallback had more than one method, a map coercion is a nice way to deal with it:
interface SingleResultCallback<T> {
def onResult(T result)
def onError
}
class Future {
def register(SingleResultCallback s) {
"registered: ${s.onResult(10)}"
}
}
assert new Future().register(
[onResult: { it ** 2 } ] as SingleResultCallback ) == "registered: 100"

I know it has been a while since the question was made, and it's already replied, but i would also to add this example using Groovy Closure as callback (to see more go at https://groovy-lang.org/closures.html).
Groovy also support Closure as an Object, for instance:
Closure callback = { println 'Done!' }
callback()
The output would be:
Done!
Above it's just another example:
def callbackList(){
def list = ["RICE", "BEANS", "EGGS"]
iterableList(list, { elem ->
println elem
})
}
def iterableList(list, callback){
list.each {
callback(it)
}
}
The output would be:
RICE
BEANS
EGGS

Related

Kotlin function parameter with receiver, called from Groovy

Kotlin and Groovy both provide a way to write a high-order function where the function parameter has an implicit receiver.
Kotlin Version
class KotlinReceiver {
fun hello() {
println("Hello from Kotlin")
}
}
class KotlinVersion {
fun withReceiver(fn: KotlinReceiver.() -> Unit) {
KotlinReceiver().fn()
}
}
// And then I can call...
val foo = KotlinVersion()
foo.withReceiver { hello() }
Groovy Version
class GroovyReceiver {
void hello() {
println("Hello from Groovy")
}
}
class GroovyVersion {
void withReceiver(Closure fn) {
fn.resolveStrategy = Closure.DELEGATE_FIRST
fn.delegate = new GroovyReceiver()
fn.run()
}
}
// And then I can call...
def foo = new GroovyVersion()
foo.withReceiver { hello() }
My goal is to write the withReceiver function in Kotlin, but call it from groovy and have { hello() } work. As written, though, Kotlin generates bytecode like
public final void withReceiver(#NotNull Function1 fn) { /* ... */ }
which Groovy treats as a function with a parameter. In other words, to call Kotlin's withReceiver from Groovy, I have to do this:
(new KotlinVersion()).withReceiver { it -> it.hello() }
In order to allow { hello() } with no it -> it., I have to add an overload that takes a groovy.lang.Closure as its parameter.
Kotlin Version
import groovy.lang.Closure
class KotlinVersion {
fun withReceiver(fn: KotlinReceiver.() -> Unit) {
KotlinReceiver().fn()
}
fun withReceiver(fn: Closure<Any>) = withReceiver {
fn.delegate = this
fn.resolveStrategy = Closure.DELEGATE_FIRST
fn.run()
}
}
With that overload in place, given a KotlinVersion instance called foo the following line works in both languages:
// If this line appears in Groovy code, it calls the Closure overload.
// If it's in Kotlin, it calls the KotlinReceiver.() -> Unit overload.
foo.withReceiver { hello() }
I'm trying to keep that syntax, but avoid having to write that extra boilerplate overload for each high-order function my Kotlin library defines. Is there a better (more seamless/automatic) way of making Kotlin's function-with-receiver syntax usable from Groovy so I don't have to manually add a boilerplate overload to each of my Kotlin functions?
The complete code and compile instructions for my toy example above are on gitlab.
in groovy you can define new functions dynamically
KotlinVersion.metaClass.withReceiver = { Closure c->
delegate.with(c)
}
this will define new function withReceiver for class KotlinVersion
and will allow to use this syntax to KotlinVersion instance:
kv.withReceiver{ toString() }
in this case toString() will be called on kv
you can write the function that iterates through declared methods of your kotlin class with kotlin.Function parameter and declare new method but with groovy.lang.Closure parameter through metaClass.

custom cast function and abstracts

This code outputs Null<_Test.Bar_Impl_>. I wanted it to output Foo but I see why it does not work that way. But may be I can somehow overcome this limitation.
My primary goal is to create function that will work like cast, but return null instead of throwing exception. And it should work with abstracts.
class Foo {
}
abstract Bar(Foo) {
}
class MyCast {
inline static public function doCast<T>(value: Any, type: Class<T>): Null<T> {
return Std.is(value, type) ? cast value : null;
}
}
class Test {
static function main() {
$type(MyCast.doCast(null, Bar));
}
}
Actually that cannot work at all like that, since Std.is(value, AbstractType) will always fail because the abstract does not exist any more at runtime.
See https://try.haxe.org/#1Afb5, and especially:
Use #:forward to access foo from Bar instances (forward doc)
Use from Foo to safe cast Foo instances into Bar instances (see implicit cast doc) (note that this feature on itself may be exactly what you were trying to achieve: https://try.haxe.org/#cc903)

On closures and groovy builder pattern

Starting to grasp closures in general and some groovy features.
Given the following code:
class Mailer {
void to(final String to) { println "to $to" }
void from(final String from) { println "from $from" }
static void send(Closure configuration) {
Mailer mailer = new Mailer()
mailer.with configuration
}
}
class MailSender {
static void sendMessage() {
Mailer.send {
to 'them'
from 'me'
}
}
}
MailSender.sendMessage()
What happens under the hood when you pass a closure to Mailer.send method?
Does to and from are passed as arguments from the Closure point of view? Which types the Closure maps them?
And then inside the Mailer.send method at the moment the Mailer object calls mailer.with receiving the configuration object, the object maps them into method calls. Groovy does this by reflection?
Groovy can dynamically define the delegate of a closure and even the this object.
with is setting the delegate and executing the closure. This is a verbose way to achieve the same:
def math = {
given 4
sum 5
print
}
class PrintMath {
def initial
def given(val) {
initial = val
}
def sum(val) {
initial += val
}
def getPrint() {
println initial
return initial
}
}
math.delegate = new PrintMath()
math.resolveStrategy = Closure.DELEGATE_ONLY
assert math() == 9
What happens under the hood when you pass a closure to Mailer.send method?
It receives a not-yet-executed block of code.
Does to and from are passed as arguments from the Closure point of view?
No, it is better thinking of them as an anonymous class/lambda in java, or a function(){} in javascript.
Which types the Closure maps them?
None, they are method calls waiting to be executed. They can be delegated to different objects, though.
And then inside the Mailer.send method at the moment the Mailer object calls mailer.with receiving the configuration object, the object maps them into method calls. Groovy does this by reflection?
You can decompile a Groovy class file to see what is going on. IIRC, Groovy currently uses a "reflector" strategy (with an arrayOfCallSite caching) to make calls faster OR it can use invokedynamic.
The closure math in the code above will result in this class:
// .. a lot of techno-babble
public Object doCall(Object it) {
CallSite[] arrayOfCallSite = $getCallSiteArray();
arrayOfCallSite[0].callCurrent(this, Integer.valueOf(4));
arrayOfCallSite[1].callCurrent(this, Integer.valueOf(5));
return arrayOfCallSite[2].callGroovyObjectGetProperty(this);
return null;
}

Groovy: Got StackOverflowError when override invokeMethod with a closure

I'm trying to enhance my Grails project with Groovy AOP approach. However I always got StackOverflowError if I override invokeMethod with a closure. Here is my test code, I can reproduce the error with groovy 2.1.3, thanks!
class A implements GroovyInterceptable
{
void foo(){
System.out.println( "A.foo");
}
}
class B extends A
{
void foo(){
System.out.println( "B.foo");
super.foo();
}
}
def mc = B.metaClass;
mc.invokeMethod = { String name, args ->
// do "before" and/or "around" work here
try {
def value = mc.getMetaMethod(name, args).invoke(delegate, args)
// do "after" work here
return value // or another value
}
catch (e) {
// do "after-throwing" work here
}
}
B b = new B();
b.foo();
Looks like, if you have a call to super() then metaClass uses the cache to find the method and throws a StackOverflow eventually. In that case if you metaClass A instead of B, it all works fine.
def mc = A.metaClass
I can infer it this way, class implementing GroovyInterceptable directly should override invokeMethod.
#Source MetaClassImpl

Using a Closure as an argument to a superclass constructor

I seem unable to use a Closure as a parameter to a superclass constructor when it is specified inline.
class Base {
def c
Base(c) {
this.c = c
}
void callMyClosure() {
c()
}
}
class Upper extends Base {
Upper() {
super( { println 'called' } )
}
}
u = new Upper()
u.callMyClosure()
The compilation fails with the message Constructor call must be the first statement in a constructor..
I realize this a somewhat strange use-case, and I can design around it for the time being. But I'm interested, is this is to be expected? Or have I got the syntax incorrect?
I think that the problem is related to the fact that Groovy turns the constructor into something different while trying to compile it as a Java class. Maybe the closure definition is expanded before the call to super generating that error.
A workaround is to define the closure outside the constructor itself:
class Base {
def c
Base(c) {this.c = c}
void callMyClosure() {
c()
}
}
class Upper extends Base {
static cc = {println 'called'}
Upper() {
super(cc)
}
}
u = new Upper()
u.callMyClosure()
It's not so nice but at least it works.. another way could be to define the closure by using a normal new Closure(...) syntax
It might be confusing a closure and a block...can you try
super( { -> println 'called' } )

Resources