[jira] [Commented] (GROOVY-8826) Captured loop variables have surprising and Java-incompatible behavior

2018-10-09 Thread Daniel Sun (JIRA)


[ 
https://issues.apache.org/jira/browse/GROOVY-8826?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16643108#comment-16643108
 ] 

Daniel Sun commented on GROOVY-8826:


[~blackdrag] Thanks for your explanation in details. You are always my good 
mentor. The issue is more complex than I thought...

Could you tell me why the following code get two {{2}}? In other words, why 
will the capatured {{i}} be changed even if the {{i}} is captured by closure. 
As far as I know, closure will store capatured variables in its instance 
fields. If we assign the value to field, even if i changed, field will hold the 
original value(i.e. 1). I do not understand why field's value will change while 
{{i}} changes(See the second following code snippet). Thanks in advance!


{code:java}
import java.util.ArrayList;
import java.util.Arrays;

public class Test {
public static void main(String... args) {
ArrayList closures = new ArrayList<>();

for (int i: new int[] {1, 2})
closures.add(() -> System.out.println(i));

for (Runnable closure: closures)
closure.run();
}
}
{code}


{code:java}

Integer i = 1

Integer f = i // if we assign the value to f, even if i changed, f will hold 
the original value, i.e. 1

i = 2

println f // gets 1

{code}



> Captured loop variables have surprising and Java-incompatible behavior
> --
>
> Key: GROOVY-8826
> URL: https://issues.apache.org/jira/browse/GROOVY-8826
> Project: Groovy
>  Issue Type: Bug
>Affects Versions: 3.0.0-alpha-3
>Reporter: Роман Донченко
>Priority: Major
>
> Consider this source:
> {code:java}
> import java.util.ArrayList;
> import java.util.Arrays;
> public class Test {
> public static void main(String... args) {
> ArrayList closures = new ArrayList<>();
> for (int i: new int[] {1, 2})
> closures.add(() -> System.out.println(i));
> for (Runnable closure: closures)
> closure.run();
> }
> }
> {code}
> If it's compiled as Java, the output is:
> {code}
> 1
> 2
> {code}
> But if it's compiled as Groovy, the output is:
> {code}
> 2
> 2
> {code}
> In other words, in Java each iteration gets a unique instance of the {{i}} 
> variable, which is captured in the corresponding closure, while in Groovy, 
> only one {{i}} variable exists and is captured into both closures. IMO, the 
> Groovy behavior is significantly less useful, and it would be nice if in 3.0 
> it was changed to match Java.
> Groovy also exhibits the same behavior with Groovy closures and 
> {{for(...in...)}} loops. I just used Java-compatible syntax for this example 
> in order to contrast Groovy and Java.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)


[jira] [Commented] (GROOVY-8826) Captured loop variables have surprising and Java-incompatible behavior

2018-10-07 Thread Daniel Sun (JIRA)


[ 
https://issues.apache.org/jira/browse/GROOVY-8826?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16640976#comment-16640976
 ] 

Daniel Sun commented on GROOVY-8826:


To clarify my opinion, we should fix the issue only when using lambda 
expression, which should behave same with Java

> Captured loop variables have surprising and Java-incompatible behavior
> --
>
> Key: GROOVY-8826
> URL: https://issues.apache.org/jira/browse/GROOVY-8826
> Project: Groovy
>  Issue Type: Bug
>Affects Versions: 3.0.0-alpha-3
>Reporter: Роман Донченко
>Priority: Major
>
> Consider this source:
> {code:java}
> import java.util.ArrayList;
> import java.util.Arrays;
> public class Test {
> public static void main(String... args) {
> ArrayList closures = new ArrayList<>();
> for (int i: new int[] {1, 2})
> closures.add(() -> System.out.println(i));
> for (Runnable closure: closures)
> closure.run();
> }
> }
> {code}
> If it's compiled as Java, the output is:
> {code}
> 1
> 2
> {code}
> But if it's compiled as Groovy, the output is:
> {code}
> 2
> 2
> {code}
> In other words, in Java each iteration gets a unique instance of the {{i}} 
> variable, which is captured in the corresponding closure, while in Groovy, 
> only one {{i}} variable exists and is captured into both closures. IMO, the 
> Groovy behavior is significantly less useful, and it would be nice if in 3.0 
> it was changed to match Java.
> Groovy also exhibits the same behavior with Groovy closures and 
> {{for(...in...)}} loops. I just used Java-compatible syntax for this example 
> in order to contrast Groovy and Java.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)


[jira] [Commented] (GROOVY-8826) Captured loop variables have surprising and Java-incompatible behavior

2018-10-07 Thread Daniel Sun (JIRA)


[ 
https://issues.apache.org/jira/browse/GROOVY-8826?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16640975#comment-16640975
 ] 

Daniel Sun commented on GROOVY-8826:


 Here is a workaround, but we should fix the issue at last...
{code:java}
import java.util.ArrayList;
import java.util.Arrays;

public class Test {
public static void main(String... args) {
ArrayList closures = new ArrayList<>();

for (int i: [1, 2]) {
int tmp = i
closures.add(() -> System.out.println(tmp));
}

for (Runnable closure: closures)
closure.run();
}
}
{code}

> Captured loop variables have surprising and Java-incompatible behavior
> --
>
> Key: GROOVY-8826
> URL: https://issues.apache.org/jira/browse/GROOVY-8826
> Project: Groovy
>  Issue Type: Bug
>Affects Versions: 3.0.0-alpha-3
>Reporter: Роман Донченко
>Priority: Major
>
> Consider this source:
> {code:java}
> import java.util.ArrayList;
> import java.util.Arrays;
> public class Test {
> public static void main(String... args) {
> ArrayList closures = new ArrayList<>();
> for (int i: new int[] {1, 2})
> closures.add(() -> System.out.println(i));
> for (Runnable closure: closures)
> closure.run();
> }
> }
> {code}
> If it's compiled as Java, the output is:
> {code}
> 1
> 2
> {code}
> But if it's compiled as Groovy, the output is:
> {code}
> 2
> 2
> {code}
> In other words, in Java each iteration gets a unique instance of the {{i}} 
> variable, which is captured in the corresponding closure, while in Groovy, 
> only one {{i}} variable exists and is captured into both closures. IMO, the 
> Groovy behavior is significantly less useful, and it would be nice if in 3.0 
> it was changed to match Java.
> Groovy also exhibits the same behavior with Groovy closures and 
> {{for(...in...)}} loops. I just used Java-compatible syntax for this example 
> in order to contrast Groovy and Java.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)