Dimitar Dimitrov created GROOVY-8045:

             Summary: Implicit closure coercion doesn't work for elements of 
array of functional objects
                 Key: GROOVY-8045
                 URL: https://issues.apache.org/jira/browse/GROOVY-8045
             Project: Groovy
          Issue Type: Bug
          Components: Compiler
    Affects Versions: 2.4.7
            Reporter: Dimitar Dimitrov

Implicit closure coercion is described 
[here|http://groovy-lang.org/releasenotes/groovy-2.2.html] - it assumes that 
the closures don't need to be casted to functional types and the generic types 
will be inferred by the compiler.

Here is one contrived case that works from Java (this is not production code 
and is writen explicitly for illustration purposes):

public class GroovyAccDemo {
    public static <T, R> Function<T, R> ensemble(Function<T, R>... hypotheses) {
        return t -> Arrays.stream(hypotheses)
                          .map(v -> v.apply(t))
                          .collect(Collectors.groupingBy(e -> e, 
                          .map(Map.Entry::getKey).orElseGet(() -> null);

    public static void main(String[] args) {
        Function<Integer, Integer> foo = ensemble(
                i -> i*i,
                i -> i+i,
                i -> i*i - (i+i)

Here the {{ensemble()}} method accepts a number of compatible functions and 
returns a single function that calls all hypotheses and returns the most 
popular result.

The main method illustrates that we can use the {{ensemble()}} function with 
Java Lambdas without any explicit casts.

If we try to do the same in Groovy, we'll get runtime error (or compile error 
if static compilation is enabled):

            foo = GroovyAccDemo.<Integer, Integer> ensemble(
                    { i -> i * i },
                    { i -> i + i },
                    { i -> i * i - (i + i) }

We can make it work by explicitly coercing the closures like this:

            foo = GroovyAccDemo.ensemble(
                    { i -> i*i } as Function,
                    { i -> i+i } as Function,
                    { i -> i*i - (i+i ) } as Function

This may seem as contrived use case, but it makes the use of certain API's more 
tedious from Groovy than from Java, which just feels wrong ;-)

This message was sent by Atlassian JIRA

Reply via email to