[ 
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)

Reply via email to