groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Andres Almiray <>
Subject Re: SAM type closure coercion
Date Wed, 18 Jan 2017 13:09:35 GMT

I almost forgot about the special arity case of defining a closure as { /*
do something */ } as it can be called with either 0 or 1 arguments, where
as { -> } accepts no arguments and { x -> } takes exactly one argument.

Would it a a good compromise to support plain typed arguments out of the
box, that is { String arg0, int arg1 -> } vs { arg0, arg1 -> } ?


Java Champion; Groovy Enthusiast
What goes up, must come down. Ask any system administrator.
There are 10 types of people in the world: Those who understand binary, and
those who don't.
To understand recursion, we must first understand recursion.

On Wed, Jan 18, 2017 at 1:52 PM, Jochen Theodorou <> wrote:

> On 18.01.2017 12:33, Remi Forax wrote:
>> I agree with Jesper,
>> solving all the cases is an uncanny valley.
>> The JEP 302 [1] has a good introduction on what javac does or not in
>> case of overloading
>> (and what currently does not work but is expected to work with java 10).
>> Also the warning proposed by Jesper exists in javac under the name
>> 'overloads'.
>> cheers,
>> RĂ©mi
>> [1]
> What Groovy currently does is look if the parameter type is a SAM type and
> then mark this as a potential match with conversion. It does not take arity
> into account, neither generics, nor the returntype of the "lambda".
> arity is a problem. {1} is a Groovy Closure with what arity? This can take
> one optional argument. {->1} is clear to take none and {x->1} is clear to
> take one argument. If we say you can use the shorter style, but then you
> may get into trouble, this is fine.
> Then there is of course not only the arity, but also the types of the
> parameters. {x->1} is an object taking Closure in Groovy. This is different
> from lambdas where the type of x may be defined by the SAM type we match
> against. So for example if I have foo(x->1+x>10) and there is a
> Predicate<String> as well as a Function<Integer,Boolean>, then of course
> the Function is supposed to be taken, but javac can try to first match
> against Predicate and if that does not work try to match against Function.
> It can see that for Integer, there is a plus method through unboxing, thus
> Function can work and if there are no further candidates the method
> selection is unambiguous, thus can be completed and no compilation error
> will happen. In dynamic Groovy we only see x of type Object. If there is a
> plus method is decided at runtime. But as such we cannot decide between the
> Predicate and the Function. Which means the Closure in the will have to be
> typed by you.
> And then of course we could get generics into the game.
> class X<T> {
>>   def foo(Function<T,Boolean> f) {..}
>>   def foo(Predicate<T> f) {..}
>> }
>> def x = new X<MyType>()
>> {Integer x-> x+1>0}
> Now for which values of MyType is this a legal call? at runtime we do not
> even have the information that x is a X<MyType>. Since we do not have that
> information, we cannot know what the T in the declaration of X means. So
> even though we used a type for x, we can still not decide here!
> And then there is the problem of the return type. What is the type of x+1
> in dynamic Groovy? We actually do not know. For x+1>0 we can infer that it
> must be boolean, because of using compareTo and that only returns a boolean
> and is enforced. But for arbitrary expressions we simply do not have the
> information before the result object is there and that is too late for the
> method selection of the method that will most likely do the invocation in
> the first place (or the invocation may never happen).
> So yes, we can improve here. But there are heavy limits for this static
> compilation controlled logic in dynamic Groovy.
> bye Jochen

View raw message