[Poll] About supporting Java-like array

classic Classic list List threaded Threaded
23 messages Options
123
Reply | Threaded
Open this post in threaded view
|

[Poll] About supporting Java-like array

Daniel.Sun
Hi all,

     As we all know, Java array is one of features widely applied in Java
projects. In order to improve the compatibility with Java(Copy & Paste). The
PR[1] will make Groovy support java-like array and make the differences[2]
with Java less and less, e.g.

*One-Dimensional array*
```
String[] names = {'Jochen', 'Paul', 'Daniel'}
```

*Two-Dimensional array*
```
int[][] data = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9},
    new int[] { 10, 11, 12 },
    {13, 14, 15}
}
```

*Annotation array*
```
@PropertySources({
    @PropertySource("classpath:1.properties"),
    @PropertySource("file:2.properties")
})
public class Controller {}
```

*More examples*
Please see the examples on the PR page[1]

*Known breaking changes*
1. Closure array in the dynamic mode
Before
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call().call() == 2
```
After
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call() == 2
```
2. String array in the dynamic mode
Before
```
String[] a = {}
assert 1 == a.length
assert a[0].contains('closure')
```
After
```
String[] a = {}
assert 0 == a.length
```


      If Groovy 3 supports Java-like array, what do you think about the new
feature? Do you like it? We need your feedback. Thanks in advance!

[+1] I like it
[ 0] Not bad
[-1] I don't like it, because...

Cheers,
Daniel.Sun
[1] https://github.com/apache/groovy/pull/691
[2] http://groovy-lang.org/differences.html




--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Users-f329450.html
Daniel Sun
Apache Groovy committer

Blog: http://blog.sunlan.me
Twitter: @daniel_sun
Reply | Threaded
Open this post in threaded view
|

Re: [Poll] About supporting Java-like array

paulk_asert
+1

For completeness, I added some more details about the breaking changes and workarounds into the issue - included below for easy reading.

Cheers, Paul.

=================

Groovy currently "promotes" a singleton instance of an object into an array for assignments, e.g.:

Integer[] nums = 42
assert nums instanceof Integer[]
assert nums.size() == 1
assert nums[0] instanceof Integer

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:

Closure[] fns0 = { }
assert fns0 instanceof Closure[]
assert fns0.size() == 1
assert fns0[0] instanceof Closure

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:

Closure[] fns1 = { }
assert fns1 instanceof Closure[]
assert fns1.size() == 0

To get the old behavior back you have a couple of options. Firstly, you can provide the explicit closure argument delimiter:

Closure[] fns2 = { -> } // can't be an array
assert fns2 instanceof Closure[]
assert fns2.size() == 1
assert fns2[0] instanceof Closure

Or don't rely on singleton promotion and explicitly provide also the array curly braces:

Closure[] fns3 = { { } }
assert fns3 instanceof Closure[]
assert fns3.size() == 1
assert fns3[0] instanceof Closure

Similarly, for the case of the identity closure:

Closure[] fns4 = { it }

Previously this worked but under this proposal will give:

groovy.lang.MissingPropertyException: No such property: it ...

Your options are to add the extra array braces as per above, or use explicit params, e.g.:

Closure[] fns5 = { it -> it }
assert fns5 instanceof Closure[]
assert fns5.size() == 1
assert fns5[0] instanceof Closure

Alternatively, for this special case you have the following additional option:

Closure[] fns6 = Closure.IDENTITY
assert fns6 instanceof Closure[]
assert fns6.size() == 1
assert fns6[0] instanceof Closure

There are other cases as well, e.g. this code which currently creates a closure array containing a closure returning the integer 0:

Closure[] fns7 = { 0 }

will no longer be supported and will fail with:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '0' with class 'java.lang.Integer' to class 'groovy.lang.Closure'
The solutions are similar to previously (explicit delimiter):

Closure[] fns8 = { -> 0 }

or (explicit outer array braces):

Closure[] fns9 = { { 0 } }


On Sun, Apr 29, 2018 at 8:37 PM, Daniel.Sun <[hidden email]> wrote:
Hi all,

     As we all know, Java array is one of features widely applied in Java
projects. In order to improve the compatibility with Java(Copy & Paste). The
PR[1] will make Groovy support java-like array and make the differences[2]
with Java less and less, e.g.

*One-Dimensional array*
```
String[] names = {'Jochen', 'Paul', 'Daniel'}
```

*Two-Dimensional array*
```
int[][] data = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9},
    new int[] { 10, 11, 12 },
    {13, 14, 15}
}
```

*Annotation array*
```
@PropertySources({
    @PropertySource("classpath:1.properties"),
    @PropertySource("file:2.properties")
})
public class Controller {}
```

*More examples*
Please see the examples on the PR page[1]

*Known breaking changes*
1. Closure array in the dynamic mode
Before
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call().call() == 2
```
After
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call() == 2
```
2. String array in the dynamic mode
Before
```
String[] a = {}
assert 1 == a.length
assert a[0].contains('closure')
```
After
```
String[] a = {}
assert 0 == a.length
```


      If Groovy 3 supports Java-like array, what do you think about the new
feature? Do you like it? We need your feedback. Thanks in advance!

[+1] I like it
[ 0] Not bad
[-1] I don't like it, because...

Cheers,
Daniel.Sun
[1] https://github.com/apache/groovy/pull/691
[2] http://groovy-lang.org/differences.html




--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Users-f329450.html

MG
Reply | Threaded
Open this post in threaded view
|

Re: [Poll] About supporting Java-like array

MG
After thinking about this some more for the last weeks
+1 with asterisk
from my side:

1) I am always for being as Java compatible as possible (though I see that this might not be feasible in all cases in the future, due to Java changing at a much faster pace and with more syntax changes now than before; example: Java considered naming the new "var" keword "def", which is similar to but not the same as Java-var in Groovy...)

2) I feel  { { } } being interpreted as an array containing an empty closure is confusing, i.e. not least surprise. I would rather not see it cut it so close with regards to what the Parrot parser can handle syntax-wise. What do others think ?

3) After introducing this syntax extension, what will be considered the "Groovy way" of initializing an array in the future ? Is it still
final int[] a = [ 1, 1, 2, 3, 5, 8 ] as int[]
or
final int[] a = { 1, 1, 2, 3, 5, 8 }
?
In the 2nd case I would be worried that the core Groovy syntax becomes all over the place over time, same as with the new Java lambda syntax (though less pronounced, since using/initializing arrays is typically rare).

4) I am not too worried about the breaking edge cases, because I feel they are quite rare in practice, the compiler catches them, and they are easy to fix.

Cheers,
mg



On 29.04.2018 15:29, Paul King wrote:
+1

For completeness, I added some more details about the breaking changes and workarounds into the issue - included below for easy reading.

Cheers, Paul.

=================

Groovy currently "promotes" a singleton instance of an object into an array for assignments, e.g.:

Integer[] nums = 42
assert nums instanceof Integer[]
assert nums.size() == 1
assert nums[0] instanceof Integer

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:

Closure[] fns0 = { }
assert fns0 instanceof Closure[]
assert fns0.size() == 1
assert fns0[0] instanceof Closure

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:

Closure[] fns1 = { }
assert fns1 instanceof Closure[]
assert fns1.size() == 0

To get the old behavior back you have a couple of options. Firstly, you can provide the explicit closure argument delimiter:

Closure[] fns2 = { -> } // can't be an array
assert fns2 instanceof Closure[]
assert fns2.size() == 1
assert fns2[0] instanceof Closure

Or don't rely on singleton promotion and explicitly provide also the array curly braces:

Closure[] fns3 = { { } }
assert fns3 instanceof Closure[]
assert fns3.size() == 1
assert fns3[0] instanceof Closure

Similarly, for the case of the identity closure:

Closure[] fns4 = { it }

Previously this worked but under this proposal will give:

groovy.lang.MissingPropertyException: No such property: it ...

Your options are to add the extra array braces as per above, or use explicit params, e.g.:

Closure[] fns5 = { it -> it }
assert fns5 instanceof Closure[]
assert fns5.size() == 1
assert fns5[0] instanceof Closure

Alternatively, for this special case you have the following additional option:

Closure[] fns6 = Closure.IDENTITY
assert fns6 instanceof Closure[]
assert fns6.size() == 1
assert fns6[0] instanceof Closure

There are other cases as well, e.g. this code which currently creates a closure array containing a closure returning the integer 0:

Closure[] fns7 = { 0 }

will no longer be supported and will fail with:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '0' with class 'java.lang.Integer' to class 'groovy.lang.Closure'
The solutions are similar to previously (explicit delimiter):

Closure[] fns8 = { -> 0 }

or (explicit outer array braces):

Closure[] fns9 = { { 0 } }


On Sun, Apr 29, 2018 at 8:37 PM, Daniel.Sun <[hidden email]> wrote:
Hi all,

     As we all know, Java array is one of features widely applied in Java
projects. In order to improve the compatibility with Java(Copy & Paste). The
PR[1] will make Groovy support java-like array and make the differences[2]
with Java less and less, e.g.

*One-Dimensional array*
```
String[] names = {'Jochen', 'Paul', 'Daniel'}
```

*Two-Dimensional array*
```
int[][] data = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9},
    new int[] { 10, 11, 12 },
    {13, 14, 15}
}
```

*Annotation array*
```
@PropertySources({
    @PropertySource("classpath:1.properties"),
    @PropertySource("file:2.properties")
})
public class Controller {}
```

*More examples*
Please see the examples on the PR page[1]

*Known breaking changes*
1. Closure array in the dynamic mode
Before
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call().call() == 2
```
After
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call() == 2
```
2. String array in the dynamic mode
Before
```
String[] a = {}
assert 1 == a.length
assert a[0].contains('closure')
```
After
```
String[] a = {}
assert 0 == a.length
```


      If Groovy 3 supports Java-like array, what do you think about the new
feature? Do you like it? We need your feedback. Thanks in advance!

[+1] I like it
[ 0] Not bad
[-1] I don't like it, because...

Cheers,
Daniel.Sun
[1] https://github.com/apache/groovy/pull/691
[2] http://groovy-lang.org/differences.html




--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Users-f329450.html


Reply | Threaded
Open this post in threaded view
|

Re: [Poll] About supporting Java-like array

Keith Suderman
I am always +1 on supporting Java syntax when practical. 

On Apr 29, 2018, at 5:17 PM, MG <[hidden email]> wrote:

2) I feel  { { } } being interpreted as an array containing an empty closure is confusing, i.e. not least surprise. I would rather not see it cut it so close with regards to what the Parrot parser can handle syntax-wise. What do others think ?

I don't like it either, but I would be willing to live with it since I'll never generate something like that myself.


3) After introducing this syntax extension, what will be considered the "Groovy way" of initializing an array in the future ? Is it still
final int[] a = [ 1, 1, 2, 3, 5, 8 ] as int[]
or
final int[] a = { 1, 1, 2, 3, 5, 8 }
?

While we are at it, could we just do:

int[] a = [ 1, 1, 2, 3, 5, 8 ]
 
without the "as int[]" at the end?  That would seem to be the "Grooviest" way IMO.

Cheers,
Keith


In the 2nd case I would be worried that the core Groovy syntax becomes all over the place over time, same as with the new Java lambda syntax (though less pronounced, since using/initializing arrays is typically rare).

4) I am not too worried about the breaking edge cases, because I feel they are quite rare in practice, the compiler catches them, and they are easy to fix.

Cheers,
mg



On 29.04.2018 15:29, Paul King wrote:
+1

For completeness, I added some more details about the breaking changes and workarounds into the issue - included below for easy reading.

Cheers, Paul.

=================

Groovy currently "promotes" a singleton instance of an object into an array for assignments, e.g.:

Integer[] nums = 42
assert nums instanceof Integer[]
assert nums.size() == 1
assert nums[0] instanceof Integer

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:

Closure[] fns0 = { }
assert fns0 instanceof Closure[]
assert fns0.size() == 1
assert fns0[0] instanceof Closure

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:

Closure[] fns1 = { }
assert fns1 instanceof Closure[]
assert fns1.size() == 0

To get the old behavior back you have a couple of options. Firstly, you can provide the explicit closure argument delimiter:

Closure[] fns2 = { -> } // can't be an array
assert fns2 instanceof Closure[]
assert fns2.size() == 1
assert fns2[0] instanceof Closure

Or don't rely on singleton promotion and explicitly provide also the array curly braces:

Closure[] fns3 = { { } }
assert fns3 instanceof Closure[]
assert fns3.size() == 1
assert fns3[0] instanceof Closure

Similarly, for the case of the identity closure:

Closure[] fns4 = { it }

Previously this worked but under this proposal will give:

groovy.lang.MissingPropertyException: No such property: it ...

Your options are to add the extra array braces as per above, or use explicit params, e.g.:

Closure[] fns5 = { it -> it }
assert fns5 instanceof Closure[]
assert fns5.size() == 1
assert fns5[0] instanceof Closure

Alternatively, for this special case you have the following additional option:

Closure[] fns6 = Closure.IDENTITY
assert fns6 instanceof Closure[]
assert fns6.size() == 1
assert fns6[0] instanceof Closure

There are other cases as well, e.g. this code which currently creates a closure array containing a closure returning the integer 0:

Closure[] fns7 = { 0 }

will no longer be supported and will fail with:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '0' with class 'java.lang.Integer' to class 'groovy.lang.Closure'
The solutions are similar to previously (explicit delimiter):

Closure[] fns8 = { -> 0 }

or (explicit outer array braces):

Closure[] fns9 = { { 0 } }


On Sun, Apr 29, 2018 at 8:37 PM, Daniel.Sun <[hidden email]> wrote:
Hi all,

     As we all know, Java array is one of features widely applied in Java
projects. In order to improve the compatibility with Java(Copy & Paste). The
PR[1] will make Groovy support java-like array and make the differences[2]
with Java less and less, e.g.

*One-Dimensional array*
```
String[] names = {'Jochen', 'Paul', 'Daniel'}
```

*Two-Dimensional array*
```
int[][] data = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9},
    new int[] { 10, 11, 12 },
    {13, 14, 15}
}
```

*Annotation array*
```
@PropertySources({
    @PropertySource("classpath:1.properties"),
    @PropertySource("file:2.properties")
})
public class Controller {}
```

*More examples*
Please see the examples on the PR page[1]

*Known breaking changes*
1. Closure array in the dynamic mode
Before
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call().call() == 2
```
After
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call() == 2
```
2. String array in the dynamic mode
Before
```
String[] a = {}
assert 1 == a.length
assert a[0].contains('closure')
```
After
```
String[] a = {}
assert 0 == a.length
```


      If Groovy 3 supports Java-like array, what do you think about the new
feature? Do you like it? We need your feedback. Thanks in advance!

[+1] I like it
[ 0] Not bad
[-1] I don't like it, because...

Cheers,
Daniel.Sun
[1] https://github.com/apache/groovy/pull/691
[2] http://groovy-lang.org/differences.html




--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Users-f329450.html



----------------------
Keith Suderman
Research Associate
Department of Computer Science
Vassar College, Poughkeepsie NY




Reply | Threaded
Open this post in threaded view
|

Re: [Poll] About supporting Java-like array

paulk_asert
In reply to this post by MG
The preferred Groovy syntax would probably still remain:

int[] fibs = [1, 1, 2, 3, 5, 8]

Cheers, Paul.

On Mon, Apr 30, 2018 at 7:17 AM, MG <[hidden email]> wrote:
After thinking about this some more for the last weeks
+1 with asterisk
from my side:

1) I am always for being as Java compatible as possible (though I see that this might not be feasible in all cases in the future, due to Java changing at a much faster pace and with more syntax changes now than before; example: Java considered naming the new "var" keword "def", which is similar to but not the same as Java-var in Groovy...)

2) I feel  { { } } being interpreted as an array containing an empty closure is confusing, i.e. not least surprise. I would rather not see it cut it so close with regards to what the Parrot parser can handle syntax-wise. What do others think ?

3) After introducing this syntax extension, what will be considered the "Groovy way" of initializing an array in the future ? Is it still
final int[] a = [ 1, 1, 2, 3, 5, 8 ] as int[]
or
final int[] a = { 1, 1, 2, 3, 5, 8 }
?
In the 2nd case I would be worried that the core Groovy syntax becomes all over the place over time, same as with the new Java lambda syntax (though less pronounced, since using/initializing arrays is typically rare).

4) I am not too worried about the breaking edge cases, because I feel they are quite rare in practice, the compiler catches them, and they are easy to fix.

Cheers,
mg




On 29.04.2018 15:29, Paul King wrote:
+1

For completeness, I added some more details about the breaking changes and workarounds into the issue - included below for easy reading.

Cheers, Paul.

=================

Groovy currently "promotes" a singleton instance of an object into an array for assignments, e.g.:

Integer[] nums = 42
assert nums instanceof Integer[]
assert nums.size() == 1
assert nums[0] instanceof Integer

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:

Closure[] fns0 = { }
assert fns0 instanceof Closure[]
assert fns0.size() == 1
assert fns0[0] instanceof Closure

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:

Closure[] fns1 = { }
assert fns1 instanceof Closure[]
assert fns1.size() == 0

To get the old behavior back you have a couple of options. Firstly, you can provide the explicit closure argument delimiter:

Closure[] fns2 = { -> } // can't be an array
assert fns2 instanceof Closure[]
assert fns2.size() == 1
assert fns2[0] instanceof Closure

Or don't rely on singleton promotion and explicitly provide also the array curly braces:

Closure[] fns3 = { { } }
assert fns3 instanceof Closure[]
assert fns3.size() == 1
assert fns3[0] instanceof Closure

Similarly, for the case of the identity closure:

Closure[] fns4 = { it }

Previously this worked but under this proposal will give:

groovy.lang.MissingPropertyException: No such property: it ...

Your options are to add the extra array braces as per above, or use explicit params, e.g.:

Closure[] fns5 = { it -> it }
assert fns5 instanceof Closure[]
assert fns5.size() == 1
assert fns5[0] instanceof Closure

Alternatively, for this special case you have the following additional option:

Closure[] fns6 = Closure.IDENTITY
assert fns6 instanceof Closure[]
assert fns6.size() == 1
assert fns6[0] instanceof Closure

There are other cases as well, e.g. this code which currently creates a closure array containing a closure returning the integer 0:

Closure[] fns7 = { 0 }

will no longer be supported and will fail with:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '0' with class 'java.lang.Integer' to class 'groovy.lang.Closure'
The solutions are similar to previously (explicit delimiter):

Closure[] fns8 = { -> 0 }

or (explicit outer array braces):

Closure[] fns9 = { { 0 } }


On Sun, Apr 29, 2018 at 8:37 PM, Daniel.Sun <[hidden email]> wrote:
Hi all,

     As we all know, Java array is one of features widely applied in Java
projects. In order to improve the compatibility with Java(Copy & Paste). The
PR[1] will make Groovy support java-like array and make the differences[2]
with Java less and less, e.g.

*One-Dimensional array*
```
String[] names = {'Jochen', 'Paul', 'Daniel'}
```

*Two-Dimensional array*
```
int[][] data = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9},
    new int[] { 10, 11, 12 },
    {13, 14, 15}
}
```

*Annotation array*
```
@PropertySources({
    @PropertySource("classpath:1.properties"),
    @PropertySource("file:2.properties")
})
public class Controller {}
```

*More examples*
Please see the examples on the PR page[1]

*Known breaking changes*
1. Closure array in the dynamic mode
Before
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call().call() == 2
```
After
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call() == 2
```
2. String array in the dynamic mode
Before
```
String[] a = {}
assert 1 == a.length
assert a[0].contains('closure')
```
After
```
String[] a = {}
assert 0 == a.length
```


      If Groovy 3 supports Java-like array, what do you think about the new
feature? Do you like it? We need your feedback. Thanks in advance!

[+1] I like it
[ 0] Not bad
[-1] I don't like it, because...

Cheers,
Daniel.Sun
[1] https://github.com/apache/groovy/pull/691
[2] http://groovy-lang.org/differences.html




--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Users-f329450.html



Reply | Threaded
Open this post in threaded view
|

Re: [Poll] About supporting Java-like array

paulk_asert
In reply to this post by Keith Suderman
Yes, what you suggested is supported and indeed the preferred way.
The `as int[]` is only needed if you have def at the front, e.g.:

def fibs = [1, 1, 2, 3, 5, 8] as int[]

Cheers, Paul.

On Mon, Apr 30, 2018 at 7:54 AM, Keith Suderman <[hidden email]> wrote:
I am always +1 on supporting Java syntax when practical. 

On Apr 29, 2018, at 5:17 PM, MG <[hidden email]> wrote:

2) I feel  { { } } being interpreted as an array containing an empty closure is confusing, i.e. not least surprise. I would rather not see it cut it so close with regards to what the Parrot parser can handle syntax-wise. What do others think ?

I don't like it either, but I would be willing to live with it since I'll never generate something like that myself.


3) After introducing this syntax extension, what will be considered the "Groovy way" of initializing an array in the future ? Is it still
final int[] a = [ 1, 1, 2, 3, 5, 8 ] as int[]
or
final int[] a = { 1, 1, 2, 3, 5, 8 }
?

While we are at it, could we just do:

int[] a = [ 1, 1, 2, 3, 5, 8 ]
 
without the "as int[]" at the end?  That would seem to be the "Grooviest" way IMO.

Cheers,
Keith


In the 2nd case I would be worried that the core Groovy syntax becomes all over the place over time, same as with the new Java lambda syntax (though less pronounced, since using/initializing arrays is typically rare).

4) I am not too worried about the breaking edge cases, because I feel they are quite rare in practice, the compiler catches them, and they are easy to fix.

Cheers,
mg



On 29.04.2018 15:29, Paul King wrote:
+1

For completeness, I added some more details about the breaking changes and workarounds into the issue - included below for easy reading.

Cheers, Paul.

=================

Groovy currently "promotes" a singleton instance of an object into an array for assignments, e.g.:

Integer[] nums = 42
assert nums instanceof Integer[]
assert nums.size() == 1
assert nums[0] instanceof Integer

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:

Closure[] fns0 = { }
assert fns0 instanceof Closure[]
assert fns0.size() == 1
assert fns0[0] instanceof Closure

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:

Closure[] fns1 = { }
assert fns1 instanceof Closure[]
assert fns1.size() == 0

To get the old behavior back you have a couple of options. Firstly, you can provide the explicit closure argument delimiter:

Closure[] fns2 = { -> } // can't be an array
assert fns2 instanceof Closure[]
assert fns2.size() == 1
assert fns2[0] instanceof Closure

Or don't rely on singleton promotion and explicitly provide also the array curly braces:

Closure[] fns3 = { { } }
assert fns3 instanceof Closure[]
assert fns3.size() == 1
assert fns3[0] instanceof Closure

Similarly, for the case of the identity closure:

Closure[] fns4 = { it }

Previously this worked but under this proposal will give:

groovy.lang.MissingPropertyException: No such property: it ...

Your options are to add the extra array braces as per above, or use explicit params, e.g.:

Closure[] fns5 = { it -> it }
assert fns5 instanceof Closure[]
assert fns5.size() == 1
assert fns5[0] instanceof Closure

Alternatively, for this special case you have the following additional option:

Closure[] fns6 = Closure.IDENTITY
assert fns6 instanceof Closure[]
assert fns6.size() == 1
assert fns6[0] instanceof Closure

There are other cases as well, e.g. this code which currently creates a closure array containing a closure returning the integer 0:

Closure[] fns7 = { 0 }

will no longer be supported and will fail with:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '0' with class 'java.lang.Integer' to class 'groovy.lang.Closure'
The solutions are similar to previously (explicit delimiter):

Closure[] fns8 = { -> 0 }

or (explicit outer array braces):

Closure[] fns9 = { { 0 } }


On Sun, Apr 29, 2018 at 8:37 PM, Daniel.Sun <[hidden email]> wrote:
Hi all,

     As we all know, Java array is one of features widely applied in Java
projects. In order to improve the compatibility with Java(Copy & Paste). The
PR[1] will make Groovy support java-like array and make the differences[2]
with Java less and less, e.g.

*One-Dimensional array*
```
String[] names = {'Jochen', 'Paul', 'Daniel'}
```

*Two-Dimensional array*
```
int[][] data = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9},
    new int[] { 10, 11, 12 },
    {13, 14, 15}
}
```

*Annotation array*
```
@PropertySources({
    @PropertySource("classpath:1.properties"),
    @PropertySource("file:2.properties")
})
public class Controller {}
```

*More examples*
Please see the examples on the PR page[1]

*Known breaking changes*
1. Closure array in the dynamic mode
Before
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call().call() == 2
```
After
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call() == 2
```
2. String array in the dynamic mode
Before
```
String[] a = {}
assert 1 == a.length
assert a[0].contains('closure')
```
After
```
String[] a = {}
assert 0 == a.length
```


      If Groovy 3 supports Java-like array, what do you think about the new
feature? Do you like it? We need your feedback. Thanks in advance!

[+1] I like it
[ 0] Not bad
[-1] I don't like it, because...

Cheers,
Daniel.Sun
[1] https://github.com/apache/groovy/pull/691
[2] http://groovy-lang.org/differences.html




--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Users-f329450.html



----------------------
Keith Suderman
Research Associate
Department of Computer Science
Vassar College, Poughkeepsie NY





MG
Reply | Threaded
Open this post in threaded view
|

Re: [Poll] About supporting Java-like array

MG
In reply to this post by paulk_asert
Well tickle my belly and colour me green - I always thought using the "as" form was mandatory here (based on the examples I saw on the net back then) :-)

That means this is the one case where giving an explicit type is the most concise way to get what you want ;-)

I would propose the Groovy compiler issue a warning to change the array initialization from Java- to Groovy-style then...
Cheers,
mg



-------- Ursprüngliche Nachricht --------
Von: Paul King <[hidden email]>
Datum: 30.04.18 00:29 (GMT+01:00)
Betreff: Re: [Poll] About supporting Java-like array

The preferred Groovy syntax would probably still remain:

int[] fibs = [1, 1, 2, 3, 5, 8]

Cheers, Paul.

On Mon, Apr 30, 2018 at 7:17 AM, MG <[hidden email]> wrote:
After thinking about this some more for the last weeks
+1 with asterisk
from my side:

1) I am always for being as Java compatible as possible (though I see that this might not be feasible in all cases in the future, due to Java changing at a much faster pace and with more syntax changes now than before; example: Java considered naming the new "var" keword "def", which is similar to but not the same as Java-var in Groovy...)

2) I feel  { { } } being interpreted as an array containing an empty closure is confusing, i.e. not least surprise. I would rather not see it cut it so close with regards to what the Parrot parser can handle syntax-wise. What do others think ?

3) After introducing this syntax extension, what will be considered the "Groovy way" of initializing an array in the future ? Is it still
final int[] a = [ 1, 1, 2, 3, 5, 8 ] as int[]
or
final int[] a = { 1, 1, 2, 3, 5, 8 }
?
In the 2nd case I would be worried that the core Groovy syntax becomes all over the place over time, same as with the new Java lambda syntax (though less pronounced, since using/initializing arrays is typically rare).

4) I am not too worried about the breaking edge cases, because I feel they are quite rare in practice, the compiler catches them, and they are easy to fix.

Cheers,
mg




On 29.04.2018 15:29, Paul King wrote:
+1

For completeness, I added some more details about the breaking changes and workarounds into the issue - included below for easy reading.

Cheers, Paul.

=================

Groovy currently "promotes" a singleton instance of an object into an array for assignments, e.g.:

Integer[] nums = 42
assert nums instanceof Integer[]
assert nums.size() == 1
assert nums[0] instanceof Integer

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:

Closure[] fns0 = { }
assert fns0 instanceof Closure[]
assert fns0.size() == 1
assert fns0[0] instanceof Closure

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:

Closure[] fns1 = { }
assert fns1 instanceof Closure[]
assert fns1.size() == 0

To get the old behavior back you have a couple of options. Firstly, you can provide the explicit closure argument delimiter:

Closure[] fns2 = { -> } // can't be an array
assert fns2 instanceof Closure[]
assert fns2.size() == 1
assert fns2[0] instanceof Closure

Or don't rely on singleton promotion and explicitly provide also the array curly braces:

Closure[] fns3 = { { } }
assert fns3 instanceof Closure[]
assert fns3.size() == 1
assert fns3[0] instanceof Closure

Similarly, for the case of the identity closure:

Closure[] fns4 = { it }

Previously this worked but under this proposal will give:

groovy.lang.MissingPropertyException: No such property: it ...

Your options are to add the extra array braces as per above, or use explicit params, e.g.:

Closure[] fns5 = { it -> it }
assert fns5 instanceof Closure[]
assert fns5.size() == 1
assert fns5[0] instanceof Closure

Alternatively, for this special case you have the following additional option:

Closure[] fns6 = Closure.IDENTITY
assert fns6 instanceof Closure[]
assert fns6.size() == 1
assert fns6[0] instanceof Closure

There are other cases as well, e.g. this code which currently creates a closure array containing a closure returning the integer 0:

Closure[] fns7 = { 0 }

will no longer be supported and will fail with:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '0' with class 'java.lang.Integer' to class 'groovy.lang.Closure'
The solutions are similar to previously (explicit delimiter):

Closure[] fns8 = { -> 0 }

or (explicit outer array braces):

Closure[] fns9 = { { 0 } }


On Sun, Apr 29, 2018 at 8:37 PM, Daniel.Sun <[hidden email]> wrote:
Hi all,

     As we all know, Java array is one of features widely applied in Java
projects. In order to improve the compatibility with Java(Copy & Paste). The
PR[1] will make Groovy support java-like array and make the differences[2]
with Java less and less, e.g.

*One-Dimensional array*
```
String[] names = {'Jochen', 'Paul', 'Daniel'}
```

*Two-Dimensional array*
```
int[][] data = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9},
    new int[] { 10, 11, 12 },
    {13, 14, 15}
}
```

*Annotation array*
```
@PropertySources({
    @PropertySource("classpath:1.properties"),
    @PropertySource("file:2.properties")
})
public class Controller {}
```

*More examples*
Please see the examples on the PR page[1]

*Known breaking changes*
1. Closure array in the dynamic mode
Before
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call().call() == 2
```
After
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call() == 2
```
2. String array in the dynamic mode
Before
```
String[] a = {}
assert 1 == a.length
assert a[0].contains('closure')
```
After
```
String[] a = {}
assert 0 == a.length
```


      If Groovy 3 supports Java-like array, what do you think about the new
feature? Do you like it? We need your feedback. Thanks in advance!

[+1] I like it
[ 0] Not bad
[-1] I don't like it, because...

Cheers,
Daniel.Sun
[1] https://github.com/apache/groovy/pull/691
[2] http://groovy-lang.org/differences.html




--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Users-f329450.html



Reply | Threaded
Open this post in threaded view
|

Re: [Poll] About supporting Java-like array

Keith Suderman
In reply to this post by Daniel.Sun


On Apr 29, 2018, at 7:10 PM, mg <[hidden email]> wrote:

Well tickle my belly and colour me green - I always thought using the "as" form was mandatory here (based on the examples I saw on the net back then) :-)

Yep me too. Learn something new every day ;) 

- Keith


That means this is the one case where giving an explicit type is the most concise way to get what you want ;-)

I would propose the Groovy compiler issue a warning to change the array initialization from Java- to Groovy-style then...
Cheers,
mg



-------- Ursprüngliche Nachricht --------
Von: Paul King <[hidden email]>
Datum: 30.04.18 00:29 (GMT+01:00)
Betreff: Re: [Poll] About supporting Java-like array

The preferred Groovy syntax would probably still remain:

int[] fibs = [1, 1, 2, 3, 5, 8]

Cheers, Paul.

On Mon, Apr 30, 2018 at 7:17 AM, MG <[hidden email]> wrote:
After thinking about this some more for the last weeks
+1 with asterisk
from my side:

1) I am always for being as Java compatible as possible (though I see that this might not be feasible in all cases in the future, due to Java changing at a much faster pace and with more syntax changes now than before; example: Java considered naming the new "var" keword "def", which is similar to but not the same as Java-var in Groovy...)

2) I feel  { { } } being interpreted as an array containing an empty closure is confusing, i.e. not least surprise. I would rather not see it cut it so close with regards to what the Parrot parser can handle syntax-wise. What do others think ?

3) After introducing this syntax extension, what will be considered the "Groovy way" of initializing an array in the future ? Is it still
final int[] a = [ 1, 1, 2, 3, 5, 8 ] as int[]
or
final int[] a = { 1, 1, 2, 3, 5, 8 }
?
In the 2nd case I would be worried that the core Groovy syntax becomes all over the place over time, same as with the new Java lambda syntax (though less pronounced, since using/initializing arrays is typically rare).

4) I am not too worried about the breaking edge cases, because I feel they are quite rare in practice, the compiler catches them, and they are easy to fix.

Cheers,
mg




On 29.04.2018 15:29, Paul King wrote:
+1

For completeness, I added some more details about the breaking changes and workarounds into the issue - included below for easy reading.

Cheers, Paul.

=================

Groovy currently "promotes" a singleton instance of an object into an array for assignments, e.g.:

Integer[] nums = 42
assert nums instanceof Integer[]
assert nums.size() == 1
assert nums[0] instanceof Integer

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:

Closure[] fns0 = { }
assert fns0 instanceof Closure[]
assert fns0.size() == 1
assert fns0[0] instanceof Closure

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:

Closure[] fns1 = { }
assert fns1 instanceof Closure[]
assert fns1.size() == 0

To get the old behavior back you have a couple of options. Firstly, you can provide the explicit closure argument delimiter:

Closure[] fns2 = { -> } // can't be an array
assert fns2 instanceof Closure[]
assert fns2.size() == 1
assert fns2[0] instanceof Closure

Or don't rely on singleton promotion and explicitly provide also the array curly braces:

Closure[] fns3 = { { } }
assert fns3 instanceof Closure[]
assert fns3.size() == 1
assert fns3[0] instanceof Closure

Similarly, for the case of the identity closure:

Closure[] fns4 = { it }

Previously this worked but under this proposal will give:

groovy.lang.MissingPropertyException: No such property: it ...

Your options are to add the extra array braces as per above, or use explicit params, e.g.:

Closure[] fns5 = { it -> it }
assert fns5 instanceof Closure[]
assert fns5.size() == 1
assert fns5[0] instanceof Closure

Alternatively, for this special case you have the following additional option:

Closure[] fns6 = Closure.IDENTITY
assert fns6 instanceof Closure[]
assert fns6.size() == 1
assert fns6[0] instanceof Closure

There are other cases as well, e.g. this code which currently creates a closure array containing a closure returning the integer 0:

Closure[] fns7 = { 0 }

will no longer be supported and will fail with:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '0' with class 'java.lang.Integer' to class 'groovy.lang.Closure'
The solutions are similar to previously (explicit delimiter):

Closure[] fns8 = { -> 0 }

or (explicit outer array braces):

Closure[] fns9 = { { 0 } }


On Sun, Apr 29, 2018 at 8:37 PM, Daniel.Sun <[hidden email]> wrote:
Hi all,

     As we all know, Java array is one of features widely applied in Java
projects. In order to improve the compatibility with Java(Copy & Paste). The
PR[1] will make Groovy support java-like array and make the differences[2]
with Java less and less, e.g.

*One-Dimensional array*
```
String[] names = {'Jochen', 'Paul', 'Daniel'}
```

*Two-Dimensional array*
```
int[][] data = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9},
    new int[] { 10, 11, 12 },
    {13, 14, 15}
}
```

*Annotation array*
```
@PropertySources({
    @PropertySource("classpath:1.properties"),
    @PropertySource("file:2.properties")
})
public class Controller {}
```

*More examples*
Please see the examples on the PR page[1]

*Known breaking changes*
1. Closure array in the dynamic mode
Before
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call().call() == 2
```
After
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call() == 2
```
2. String array in the dynamic mode
Before
```
String[] a = {}
assert 1 == a.length
assert a[0].contains('closure')
```
After
```
String[] a = {}
assert 0 == a.length
```


      If Groovy 3 supports Java-like array, what do you think about the new
feature? Do you like it? We need your feedback. Thanks in advance!

[+1] I like it
[ 0] Not bad
[-1] I don't like it, because...

Cheers,
Daniel.Sun
[1] https://github.com/apache/groovy/pull/691
[2] http://groovy-lang.org/differences.html




--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Users-f329450.html




----------------------
Keith Suderman
Research Associate
Department of Computer Science
Vassar College, Poughkeepsie NY




Reply | Threaded
Open this post in threaded view
|

Re: [Poll] About supporting Java-like array

paulk_asert
In reply to this post by paulk_asert


On Mon, Apr 30, 2018 at 9:10 AM, mg <[hidden email]> wrote:
I would propose the Groovy compiler issue a warning to change the array initialization from Java- to Groovy-style then...

A codenarc rule would be a great first option.
 
Cheers,
mg



-------- Ursprüngliche Nachricht --------
Von: Paul King <[hidden email]>
Datum: 30.04.18 00:29 (GMT+01:00)
Betreff: Re: [Poll] About supporting Java-like array

The preferred Groovy syntax would probably still remain:

int[] fibs = [1, 1, 2, 3, 5, 8]

Cheers, Paul.

On Mon, Apr 30, 2018 at 7:17 AM, MG <[hidden email]> wrote:
After thinking about this some more for the last weeks
+1 with asterisk
from my side:

1) I am always for being as Java compatible as possible (though I see that this might not be feasible in all cases in the future, due to Java changing at a much faster pace and with more syntax changes now than before; example: Java considered naming the new "var" keword "def", which is similar to but not the same as Java-var in Groovy...)

2) I feel  { { } } being interpreted as an array containing an empty closure is confusing, i.e. not least surprise. I would rather not see it cut it so close with regards to what the Parrot parser can handle syntax-wise. What do others think ?

3) After introducing this syntax extension, what will be considered the "Groovy way" of initializing an array in the future ? Is it still
final int[] a = [ 1, 1, 2, 3, 5, 8 ] as int[]
or
final int[] a = { 1, 1, 2, 3, 5, 8 }
?
In the 2nd case I would be worried that the core Groovy syntax becomes all over the place over time, same as with the new Java lambda syntax (though less pronounced, since using/initializing arrays is typically rare).

4) I am not too worried about the breaking edge cases, because I feel they are quite rare in practice, the compiler catches them, and they are easy to fix.

Cheers,
mg




On 29.04.2018 15:29, Paul King wrote:
+1

For completeness, I added some more details about the breaking changes and workarounds into the issue - included below for easy reading.

Cheers, Paul.

=================

Groovy currently "promotes" a singleton instance of an object into an array for assignments, e.g.:

Integer[] nums = 42
assert nums instanceof Integer[]
assert nums.size() == 1
assert nums[0] instanceof Integer

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:

Closure[] fns0 = { }
assert fns0 instanceof Closure[]
assert fns0.size() == 1
assert fns0[0] instanceof Closure

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:

Closure[] fns1 = { }
assert fns1 instanceof Closure[]
assert fns1.size() == 0

To get the old behavior back you have a couple of options. Firstly, you can provide the explicit closure argument delimiter:

Closure[] fns2 = { -> } // can't be an array
assert fns2 instanceof Closure[]
assert fns2.size() == 1
assert fns2[0] instanceof Closure

Or don't rely on singleton promotion and explicitly provide also the array curly braces:

Closure[] fns3 = { { } }
assert fns3 instanceof Closure[]
assert fns3.size() == 1
assert fns3[0] instanceof Closure

Similarly, for the case of the identity closure:

Closure[] fns4 = { it }

Previously this worked but under this proposal will give:

groovy.lang.MissingPropertyException: No such property: it ...

Your options are to add the extra array braces as per above, or use explicit params, e.g.:

Closure[] fns5 = { it -> it }
assert fns5 instanceof Closure[]
assert fns5.size() == 1
assert fns5[0] instanceof Closure

Alternatively, for this special case you have the following additional option:

Closure[] fns6 = Closure.IDENTITY
assert fns6 instanceof Closure[]
assert fns6.size() == 1
assert fns6[0] instanceof Closure

There are other cases as well, e.g. this code which currently creates a closure array containing a closure returning the integer 0:

Closure[] fns7 = { 0 }

will no longer be supported and will fail with:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '0' with class 'java.lang.Integer' to class 'groovy.lang.Closure'
The solutions are similar to previously (explicit delimiter):

Closure[] fns8 = { -> 0 }

or (explicit outer array braces):

Closure[] fns9 = { { 0 } }


On Sun, Apr 29, 2018 at 8:37 PM, Daniel.Sun <[hidden email]> wrote:
Hi all,

     As we all know, Java array is one of features widely applied in Java
projects. In order to improve the compatibility with Java(Copy & Paste). The
PR[1] will make Groovy support java-like array and make the differences[2]
with Java less and less, e.g.

*One-Dimensional array*
```
String[] names = {'Jochen', 'Paul', 'Daniel'}
```

*Two-Dimensional array*
```
int[][] data = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9},
    new int[] { 10, 11, 12 },
    {13, 14, 15}
}
```

*Annotation array*
```
@PropertySources({
    @PropertySource("classpath:1.properties"),
    @PropertySource("file:2.properties")
})
public class Controller {}
```

*More examples*
Please see the examples on the PR page[1]

*Known breaking changes*
1. Closure array in the dynamic mode
Before
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call().call() == 2
```
After
```
Closure[] y = { {-> 1 + 1 } }
assert y[0].call() == 2
```
2. String array in the dynamic mode
Before
```
String[] a = {}
assert 1 == a.length
assert a[0].contains('closure')
```
After
```
String[] a = {}
assert 0 == a.length
```


      If Groovy 3 supports Java-like array, what do you think about the new
feature? Do you like it? We need your feedback. Thanks in advance!

[+1] I like it
[ 0] Not bad
[-1] I don't like it, because...

Cheers,
Daniel.Sun
[1] https://github.com/apache/groovy/pull/691
[2] http://groovy-lang.org/differences.html




--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Users-f329450.html





Reply | Threaded
Open this post in threaded view
|

Re: [Poll] About supporting Java-like array

Daniel Sun
In reply to this post by MG
Hi mg,

     As far as I remember, two dimensional array like`int[][] a = [[1, 2,
3], [4, 5, 6]]` will go wrong in the Groovy style.

Cheers,
Daniel.Sun




--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Users-f329450.html
123