[ https://issues.apache.org/jira/browse/GROOVY-8561?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Eric Milles updated GROOVY-8561: -------------------------------- Priority: Minor (was: Major) > Support java-like array > ----------------------- > > Key: GROOVY-8561 > URL: https://issues.apache.org/jira/browse/GROOVY-8561 > Project: Groovy > Issue Type: New Feature > Reporter: Daniel Sun > Assignee: Daniel Sun > Priority: Minor > > Groovy currently "promotes" a singleton instance of an object into an array > for assignments, e.g.: > {code:java} > Integer[] nums = 42 > assert nums instanceof Integer[] > assert nums.size() == 1 > assert nums[0] instanceof Integer > {code} > This aligns with how Groovy behaves if you try to call `.each{}` on a > non-aggregate. It treats it like a singleton collection and "iterates" over > the one item. > The existing behavior also currently works for singleton Closures: > {code:java} > Closure[] fns0 = { } > assert fns0 instanceof Closure[] > assert fns0.size() == 1 > assert fns0[0] instanceof Closure > {code} > To add support for Java array notation, we will need to partially disable > this behavior. The proposed change involves smart parsing, e.g. it will > distinguish cases which must be an array and cases which must be a closure > but there are some degenerate edge cases which will become breaking changes. > The case with the empty closure above will no longer work, instead you will > get this behavior, i.e. an empty array is given precedence over an empty > closure: > {code:java} > Closure[] fns1 = { } > assert fns1 instanceof Closure[] > assert fns1.size() == 0 > {code} > To get the old behavior back you have a couple of options. Firstly, you can > provide the explicit closure argument delimiter: > {code:java} > Closure[] fns2 = { -> } // can't be an array > assert fns2 instanceof Closure[] > assert fns2.size() == 1 > assert fns2[0] instanceof Closure > {code} > Or don't rely on singleton promotion and explicitly provide also the array > curly braces: > {code:java} > Closure[] fns3 = { { } } > assert fns3 instanceof Closure[] > assert fns3.size() == 1 > assert fns3[0] instanceof Closure > {code} > Similarly, for the case of the identity closure: > {code:java} > Closure[] fns4 = { it } > {code} > Previously this worked but under this proposal will give: > {noformat} > groovy.lang.MissingPropertyException: No such property: it ... > {noformat} > Your options are to add the extra array braces as per above, or use explicit > params, e.g.: > {code:java} > Closure[] fns5 = { it -> it } > assert fns5 instanceof Closure[] > assert fns5.size() == 1 > assert fns5[0] instanceof Closure > {code} > Alternatively, for this special case you have the following additional option: > {code:java} > Closure[] fns6 = Closure.IDENTITY > assert fns6 instanceof Closure[] > assert fns6.size() == 1 > assert fns6[0] instanceof Closure > {code} > There are other cases as well, e.g. this code which currently creates a > closure array containing a closure returning the integer 0: > {code:java} > Closure[] fns7 = { 0 } > {code} > will no longer be supported and will fail with: > {noformat} > org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast > object '0' with class 'java.lang.Integer' to class 'groovy.lang.Closure' > {noformat} > The solutions are similar to previously (explicit delimiter): > {code:java} > Closure[] fns8 = { -> 0 } > {code} > or (explicit outer array braces): > {code:java} > Closure[] fns9 = { { 0 } } > {code} > Here is the PR: [https://github.com/apache/groovy/pull/691] -- This message was sent by Atlassian Jira (v8.20.10#820010)