You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Eric Milles (Jira)" <ji...@apache.org> on 2022/05/25 19:10:00 UTC

[jira] [Assigned] (GROOVY-8045) Implicit closure coercion doesn't work for elements of array of functional objects

     [ https://issues.apache.org/jira/browse/GROOVY-8045?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Eric Milles reassigned GROOVY-8045:
-----------------------------------

    Assignee: Eric Milles

> 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
>            Assignee: Eric Milles
>            Priority: Major
>              Labels: varargs
>
> 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):
> {code}
> public class GroovyAccDemo {
>     @SafeVarargs
>     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, Collectors.counting()))
>                           .entrySet()
>                           .stream()
>                           .max(Comparator.comparingLong(Map.Entry::getValue))
>                           .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)
>         );
>     }
> }
> {code}
> 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):
> {code}
>             foo = GroovyAccDemo.<Integer, Integer> ensemble(
>                     { i -> i * i },
>                     { i -> i + i },
>                     { i -> i * i - (i + i) }
>             );
> {code}
> We can make it work by explicitly coercing the closures like this:
> {code}
>             foo = GroovyAccDemo.ensemble(
>                     { i -> i*i } as Function,
>                     { i -> i+i } as Function,
>                     { i -> i*i - (i+i ) } as Function
>             );
> {code}
> 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
(v8.20.7#820007)