|
I just want to make sure I am not missing something and that this is not intentional before I post a bug.
Groovy 1.5.4, Java 1.5.0_14, GroovyConsole def variable = "I'm in UR Script/Scoping UR Variables" def method() { println variable } closure = { println variable } closure() // works method() // fails calling closure works as expected, calling method throws: groovy.lang.MissingPropertyException: No such property: variable for class: Script1 Am I unaware of some scripting nuance or is this a bug? It feels like a bug. ------------------------------------------------------ I'm Danno Ferrin, and I approved this message. |
|
I thin the scope of this varaible is local to the run() method and therefore not accessible to another method.The scope of the closure is the binding since you didn't def it. If you had, it would have been local to the run method anyway. If you want to have the variable accessible by the method, remove def. HTH pascal On Thursday 13 March 2008, Danno Ferrin wrote: > I just want to make sure I am not missing something and that this is not > intentional before I post a bug. > > Groovy 1.5.4, Java 1.5.0_14, GroovyConsole > > def variable = "I'm in UR Script/Scoping UR Variables" > > def method() { println variable } > closure = { println variable } > > closure() // works > method() // fails > > calling closure works as expected, calling method throws: > groovy.lang.MissingPropertyException: No such property: variable for class: > Script1 > > Am I unaware of some scripting nuance or is this a bug? It feels like a > bug. > > ------------------------------------------------------ > I'm Danno Ferrin, and I approved this message. |
|
In reply to this post by Danno Ferrin
Danno Ferrin schrieb:
> I just want to make sure I am not missing something and that this is not > intentional before I post a bug. > > Groovy 1.5.4, Java 1.5.0_14, GroovyConsole > > def variable = "I'm in UR Script/Scoping UR Variables" > > def method() { println variable } > closure = { println variable } > > closure() // works > method() // fails > > calling closure works as expected, calling method throws: > groovy.lang.MissingPropertyException: No such property: variable for > class: Script1 > > Am I unaware of some scripting nuance or is this a bug? It feels like a > bug. it is a script nuance, let me try to explain... First, think of these rules: 1.) any script is also a class 2.) Groovy does not support methods in methods 3.) Groovy supports a global context through the binding now if you think about your code, then you will see, that according to rule 1 we need to transform this into a class: class script1 { def run() { def variable = "...." def method() {println variable} closure = {println variable} closure() method() } } and then you will see, that this is not allowed because of rule 2: class script2 { def method() {println variable} def run() { def variable = "...." closure = {println variable} closure() method() } } as you can see now, the variable "variable" is defined in run, but not in method. But we do also set closure without defining it before. This is where rule 3 kicks in: class script2 { Binding binding = new Binding(); def getProperty(String name) { try {return metaclass.getProperty(name)} if (it fails) return binding."$name" } void setProperty(String name, value) { try { metaclass.setProperty,value)} if (itfails) binding."$name" = value } def method() {println variable} def run() { def variable = "...." closure = {println variable} closure() method() } } and then you will see, that when we set the closure we really set the value binding.closure and when we ask for variable in method, we really ask binding for a value for "variable". Since binding will throw a MissingPropertyException when you ask it for a value before the value has been set, you get the exception you have seen. Another way to explain this would be, that while a closure has the ability to close over a local scope a method can close only over the class scope. Since a script has no such scope there is no way a method could access a local variable defined outside the method. But of course the closure is fine. Not sure which way you prefer ;) bye blackdrag -- Jochen "blackdrag" Theodorou The Groovy Project Tech Lead (http://groovy.codehaus.org) http://blackdragsview.blogspot.com/ http://www.g2one.com/ --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
On 3/13/08, Jochen Theodorou <[hidden email]> wrote: Danno Ferrin schrieb: But my fundamental question: is this accepted emergent behaviro from the implementation or was there some deliverate rationale for this? Going to the first of the three rules, a script is a class, how do I define a field in the class? Clearly the script is not a method, because of rule 1 and rule 2 prohibits defining methods in methods, so why are they moved to become method variables instead of class fields. Why couldn't the script be translated by the compiler to pull the declarations into class fields/properties, but leaving the initialization in the class where declared, allowing variables to have script/class scope... class script4 { def variable def method() {println variable} def run() { variable = "...." closure = {println variable} closure() method() } } Is this just emergent from the way it was done the first time, or was there some reason for it? (as an aside, why are method variables allowed to have a scope modifier? More emergent behavior from the grammer? def method() { protected v2 = variable*2 // works } ) ------------------------------------------------------ I'm Danno Ferrin, and I approved this message. |
|
Danno Ferrin schrieb:
[...] > But my fundamental question: is this accepted emergent behaviro from the > implementation or was there some deliverate rationale for this? that's why I posted two explanations. Methods are no closures, it is as simple as that. > Going to the first of the three rules, a script is a class, how do I > define a field in the class? in a script you do not. > Clearly the script is not a method, > because of rule 1 and rule 2 prohibits defining methods in methods, so > why are they moved to become method variables instead of class fields. well can you explain why in """ def foo=null bar=null """ foo should become a field and bar not? If you are going to say, because the def indicates that, then it is very weak. Even more weak than saying that the def indicates that a local variable is declared. At last this one is consistent unless you are in a class body. But since a script has no visible class, you can not be in a class body, so getting always a local variable seems to be the most consistent way to me. And not only that... """ def m(){foo} foo="a" assert m()=="a" def foo="b" assert m()=="b" """ in this script if we follow the current rules, then the second assert will fail. If we say "def foo" creates a field, then the first assert will fail. But we can increase the factor of disturbing pitfalls a bit: """ def foo=null if (true) { def foo=null } """ in normal Groovy this will not compile. If we say the first def will make a field and the second def a local variable, then we could theoretically compile this.. which does not mean we have to of course... but worse: """ if (true) { def foo=null } def foo=null """ this case would compile in current Groovy, but depending on if we allow a local variable of the same name as a field in a script or not this script won't. Ah, yes, there is also: """ def m() {foo} assert m()==null def foo=1 assert m()==1 """ this script would work if we would make the foo into a field. In current Groovy this would throw a MissingPropertyException for the first assert and the second assert > Why couldn't the script be translated by the compiler to pull the > declarations into class fields/properties, but leaving the > initialization in the class where declared, allowing variables to have > script/class scope... I tried to show some corner cases this introduces. [...] > Is this just emergent from the way it was done the first time, or was > there some reason for it? I think basically it was from how it was done the first time, but I find that way more explainable than the other way. > (as an aside, why are method variables allowed to have a scope > modifier? More emergent behavior from the grammer? > def method() { > protected v2 = variable*2 // works > } > ) yes, the check to throw an exception for this is missing. The infrastructure is already in APP, Paul added things for these kind of checks, but this part is simply not checked there bye blackdrag -- Jochen "blackdrag" Theodorou The Groovy Project Tech Lead (http://groovy.codehaus.org) http://blackdragsview.blogspot.com/ http://www.g2one.com/ --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
On 3/13/08, Jochen Theodorou <[hidden email]> wrote: """Danno Ferrin schrieb: Like I said in my previous e-mail, it's the decleration of variables that flags it as becoming a field. foo is a decleration with an initializer, whereas bar is simply an assignment expression. foo should become a field and bar not? If you are going to say, because Why is saying it weak? Because it is the simplest answer? What objective standard exists other than your opinion that it is weak? If in yout opinion it is an insufficiant ansewer state as such and that would be sufficient, I fail to see the need to critique the argument when the argument has not been presented. Even more weak than saying Class bodies do not accept assignment expressions outside the context of a decleration at the class level. They must be static initializers, instance initializers, or methods. There is no comparison to be made because the grammer prohibits it. But since a script has It depends on the view of what a script is, and I am not certain that there has been much exposition on that topic except for what the emergent behavior from the "place it in a run method" and necessary adjustments such as pulling out methods and such. And not only A similar result can be obtained in Java """ class fieldMasking { static String foo = "x"; static Object m() { return foo;} public static void main(String arg[]) { foo = "a"; assert m().equals("a"); String foo = "b"; assert m().equals("b"); } } """ (be sure to run with assertions enalbed, Java 1.5 turns them off by default, 'java -ea -cp . fieldMasking') This example isn't a perfect translation since Java doesn't have an exterior scope for bindings. A similar case can be made with callalble. """ import java.util.concurrent.*; class fieldMasking { static String foo = "x"; public static void main(String arg[]) throws Exception { Callable<String> m = new Callable<String>() { public String call() { return foo; } }; foo = "a"; assert m.call().equals("a"); String foo = "b"; assert m.call().equals("b"); } } """ in this script if we follow the current rules, then the second assert In the case of Java, it is always the second assert that fails. And when it is seen in context of a Java class it is a bit more obvious, since the decleration in the static class scope is explicit. If we were to implement it then we would want to match existing conventions and fail like Java did. But we can increase the factor of disturbing pitfalls a bit: in normal Groovy this will not compile. If we say the first def will Similarly it fails in Java, we should leave that part as is. """ This is a very good case. The rule would need to be defined to create fields for top level declerations only. Similarly we wouldn't want a field declared in this case: """ if (true) { def foo=null } """ this case would compile in current Groovy, but depending on if we allow Unless we call the script with a binding that has foo already defined. Similar things are done in SwingBuilder when using the build() node. > Why couldn't the script be translated by the compiler to pull the This is really the answer I am looking for, and it is satisfactory. In thinking about this I had in my mind that it may be cool to declare "naked script" classes. But then you lose the ability to extend or implement. And of we want to make such naked script classes usable we would start going down the path of duck typeing, which is something that would confuse most users even more than the corner cases illustrated here. So there really isn't much to be gained by changing the behavior, just another nuacne to suprise. The reason it even came up is some of the people starting to use Groovy at my company aren't quite comfortable with the use of undeclared variables. Old school java runs very deep at my company, I'm just happy we are baselined on 1.5 and can use Generics! > (as an aside, why are method variables allowed to have a scope Perhaps we should look into adding the static modifier to script declerations to the list, it looks also like it has no effect. static String variable = "I'm in UR Script/Scoping UR Variables" def method() { println variable } closure = { println variable } closure() // works method() // still fails """ ------------------------------------------------------ I'm Danno Ferrin, and I approved this message. |
|
In reply to this post by Jochen Theodorou
On Thu, 2008-03-13 at 20:05 +0100, Jochen Theodorou wrote: > class script1 { > def run() { > def variable = "...." > def method() {println variable} > closure = {println variable} > > closure() > method() > } > } > class script2 { > def method() {println variable} > def run() { > def variable = "...." > closure = {println variable} > > closure() > method() > } > } is to be moved in scope then the variable should as well. The semantics of scripts on this point is counter intuitive and causes a lot of people a lot of irritation. Of course we should get actual data on this point rather than just relying on my assumptions and prejudice. -- Russel. ==================================================== Dr Russel Winder Partner Concertant LLP t: +44 20 7193 9203 41 Buckmaster Road, f: +44 8700 516 084 London SW11 1EN, UK. m: +44 7770 465 077 |
|
In reply to this post by Danno Ferrin
On Thu, 2008-03-13 at 15:15 -0600, Danno Ferrin wrote: > But my fundamental question: is this accepted emergent behaviro from > the implementation or was there some deliverate rationale for this? It is a hack to get round a problem of code generation that has been turned into a principle that people have been forced to accept. > class script4 { > def variable > def method() {println variable} > def run() { > variable = "...." > closure = {println variable} > > closure() > method() > } > } I suggest raising a JIRA issue on this. I would propose 1.6 rather than 2.0 as the version for solution. Yes it is a breaking change, but for the better. -- Russel. ==================================================== Dr Russel Winder Partner Concertant LLP t: +44 20 7193 9203 41 Buckmaster Road, f: +44 8700 516 084 London SW11 1EN, UK. m: +44 7770 465 077 |
|
In reply to this post by Jochen Theodorou
On Thu, 2008-03-13 at 23:17 +0100, Jochen Theodorou wrote: > > Going to the first of the three rules, a script is a class, how do I > > define a field in the class? > > in a script you do not. Just because you can't at the moment, doesn't mean things should not change. > > Clearly the script is not a method, > > because of rule 1 and rule 2 prohibits defining methods in methods, so > > why are they moved to become method variables instead of class fields. > > well can you explain why in > > """ > def foo=null > bar=null > """ > > foo should become a field and bar not? If you are going to say, because > the def indicates that, then it is very weak. Even more weak than saying > that the def indicates that a local variable is declared. At last this > one is consistent unless you are in a class body. But since a script has > no visible class, you can not be in a class body, so getting always a > local variable seems to be the most consistent way to me. And not only > that... in the binding. I don't follow the rest of the argument. [ . . . ] -- Russel. ==================================================== Dr Russel Winder Partner Concertant LLP t: +44 20 7193 9203 41 Buckmaster Road, f: +44 8700 516 084 London SW11 1EN, UK. m: +44 7770 465 077 |
|
Russel Winder schrieb:
[...] >> """ >> def foo=null >> bar=null >> """ >> >> foo should become a field and bar not? If you are going to say, because >> the def indicates that, then it is very weak. Even more weak than saying >> that the def indicates that a local variable is declared. At last this >> one is consistent unless you are in a class body. But since a script has >> no visible class, you can not be in a class body, so getting always a >> local variable seems to be the most consistent way to me. And not only >> that... > > All the def does is say this variable is found here, do not look it up > in the binding. I don't follow the rest of the argument. it does not say "this variable is found here", that is not the way it works. """ foo=null def foo=null """ in Groovy this is a legal script. the first line sets the value null for "foo" in the binding and the second one defines a local variable, meaning that the name foo changes its meaning from this point on. Indeed, if I would make the def line a field definition, then foo would be a reference to the field instead of the binding, thus your "his variable is found here" would be right. But think about this: """ foo=null if (true){ def foo=null } """ what will tis do? In current Groovy the first line will again access the binding, the def line will create a local variable, that shadows the binding, but only for the time the if-block is processed and only after the right side of the declaration is processed... yes, another example for what is possible at the moment: """ foo = 1 def foo = foo """ If I change foo to become a field because of the usage of def, then this code has to be illegal, while it is currently perfectly legal. So in short, "this variable is found here" does not fit with the concept of nested scopes. A change from local variable to field is a major change to the semantics at multiple places.. I would not vote for putting that into 1.6, not without indicator. More interesting would be the usage of an annotation to tell the compiler that this should be a field/property instead of a local variable. This way would compatible with what we have now. bye blackdrag -- Jochen "blackdrag" Theodorou The Groovy Project Tech Lead (http://groovy.codehaus.org) http://blackdragsview.blogspot.com/ http://www.g2one.com/ --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
In reply to this post by Russel Winder-2
Russel Winder schrieb:
> On Thu, 2008-03-13 at 20:05 +0100, Jochen Theodorou wrote: > >> class script1 { >> def run() { >> def variable = "...." >> def method() {println variable} >> closure = {println variable} >> >> closure() >> method() >> } >> } > >> class script2 { >> def method() {println variable} >> def run() { >> def variable = "...." >> closure = {println variable} >> >> closure() >> method() >> } >> } > > This code transformation has always struck me as wrong. If the method > is to be moved in scope then the variable should as well. maybe, but while this is not possible: """ if (true) { def m(){1} m() } """ this one is: """ if (true) { def var = 1 } """ bye blackdrag -- Jochen "blackdrag" Theodorou The Groovy Project Tech Lead (http://groovy.codehaus.org) http://blackdragsview.blogspot.com/ http://www.g2one.com/ --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
In reply to this post by Danno Ferrin
Danno Ferrin schrieb:
[...] > > Is this just emergent from the way it was done the first time, or was > > there some reason for it? > > I think basically it was from how it was done the first time, but I find > that way more explainable than the other way. > > This is really the answer I am looking for, and it is satisfactory. ok, good... EOT? *g* > In thinking about this I had in my mind that it may be cool to declare > "naked script" classes. But then you lose the ability to extend or > implement. And of we want to make such naked script classes usable we > would start going down the path of duck typeing, which is something that > would confuse most users even more than the corner cases illustrated > here. So there really isn't much to be gained by changing the behavior, > just another nuacne to suprise. I agree > The reason it even came up is some of the people starting to use Groovy > at my company aren't quite comfortable with the use of undeclared > variables. Old school java runs very deep at my company, I'm just happy > we are baselined on 1.5 and can use Generics! what we currently have is not a clean separation in scripts. I won't deny it. If we would for example enforce that a method definition is not possible between normal statements, then it would be more clear too I guess... But I think the current way is good enough if you go and always tell that methods can not see local variables defined outside the method and that a declaration in script always defines a local variable. I personally do not work much with the binding. I usually use classes, or maps or expandos. I usually use the binding only if I want to share information between scripts, but even then I usually do not use plain values. Ah, yes.. and in scripts I work mostly with closures, so the method problem does not happen to me. > > (as an aside, why are method variables allowed to have a scope > > modifier? More emergent behavior from the grammer? > > def method() { > > protected v2 = variable*2 // works > > } > > ) > > > yes, the check to throw an exception for this is missing. The > infrastructure is already in APP, Paul added things for these kind of > checks, but this part is simply not checked there > > Perhaps we should look into adding the static modifier to script > declerations to the list, it looks also like it has no effect. > > """ > static String variable = "I'm in UR Script/Scoping UR Variables" > > def method() { println variable } > closure = { println variable } > > closure() // works > method() // still fails > """ sorry, I don't get it... what exactly is the static modifier doing here? bye blackdrag -- Jochen "blackdrag" Theodorou The Groovy Project Tech Lead (http://groovy.codehaus.org) http://blackdragsview.blogspot.com/ http://www.g2one.com/ --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
In reply to this post by Jochen Theodorou
On Fri, 2008-03-14 at 15:18 +0100, Jochen Theodorou wrote: > """ > foo=null > def foo=null > """ > > in Groovy this is a legal script. the first line sets the value null for > "foo" in the binding and the second one defines a local variable, But a local variable in what scope. The point being made is that there is inconsistent manipulation of methods and variables. > meaning that the name foo changes its meaning from this point on. Not entirely true. foo = 1 def foo = 2 println ( foo ) def c = { println ( foo ) } c ( ) def d ( ) { println ( foo ) } d ( ) c and d are at the same scope in this script but the search rules are totally different. I find this inconsistent and unjustifiable. There is no need to repeat why it works this way in Groovy, I know that. This is a case of finding an argument as to why this is the correct behaviour in your opinion. My view is that the behaviour is wrong and should be changed so as to make it consistent from the point of view of the script as the thing being programmed. I should not have to know how the script is converted into a class in order to be able to understand the behaviour. > Indeed, if I would make the def line a field definition, then foo would > be a reference to the field instead of the binding, thus your "his > variable is found here" would be right. But think about this: That is good then. > """ > foo=null > if (true){ > def foo=null > } > """ > > what will tis do? In current Groovy the first line will again access the > binding, the def line will create a local variable, that shadows the > binding, but only for the time the if-block is processed and only after > the right side of the declaration is processed... yes, another example > for what is possible at the moment: > """ > foo = 1 > def foo = foo > """ > > If I change foo to become a field because of the usage of def, then this > code has to be illegal, while it is currently perfectly legal. Why? > So in short, "this variable is found here" does not fit with the concept > of nested scopes. A change from local variable to field is a major > change to the semantics at multiple places.. I would not vote for > putting that into 1.6, not without indicator. The current semantics are inconsistent and incomprehensible to anyone who does not learn the intimate details about how a script is turned into a class. What indicator do you need to make the change? Let me know what the metric is and I will set about ensuring that it happens. Unless someone can convince me that the current semantic is the only sane one. > More interesting would be the usage of an annotation to tell the > compiler that this should be a field/property instead of a local > variable. This way would compatible with what we have now. Why patch a bad situation when you can do a proper fix? -- Russel. ==================================================== Dr Russel Winder Partner Concertant LLP t: +44 20 7193 9203 41 Buckmaster Road, f: +44 8700 516 084 London SW11 1EN, UK. m: +44 7770 465 077 |
|
In reply to this post by Jochen Theodorou
On 3/14/08, Jochen Theodorou <[hidden email]> wrote: Russel Winder schrieb: That is exactly the thought I was having. It also provides a place to place instance-initialization of the variable when he script is first instantiated (in the annotation text). Making the decleartions always fields creates some more confusing cases... """ def count println count++ """ multiple calls to run would make count run up from zero, but what if you wanted to start at 1? """ def count = 1 println count++ """ you'de either always get 1, or prevent scripts from re-initializing things such as counting fields. """ @Field(init='1') int count println count++ @Field(init='"x"') String s """ However it doesn't look quite as good :( Other than the case of getting rid of nuance education I can't think of a compelling use case to make script variables that makes it simpler than slapping it inside of a Callable or a static main. ------------------------------------------------------ I'm Danno Ferrin, and I approved this message. |
|
In reply to this post by Jochen Theodorou
> > (as an aside, why are method variables allowed to have a scope Nothing, it appears to be functionally identical to the version w/o static. Reading the script it would lead me to believe that the variable will be stored statically as part of the script class, bit it's not. That's why I think it should make a compiler error, since it does nothing but implies something that isn't happening, like scope modifiers in method variables. ------------------------------------------------------ I'm Danno Ferrin, and I approved this message. |
|
In reply to this post by Russel Winder-2
I gotta agree with Russel here, remember he stands to be hit the
hardest by this change as the author of Gant. The fact is the whole way scoping rules work in Groovy scripts is counter intuitive. Of course we can try to persuade ourselves that it is this way because of x,y and z. But really we have to ask ourselves why can't we make it into something sane? Cheers On Fri, Mar 14, 2008 at 3:21 PM, Russel Winder <[hidden email]> wrote: > > On Fri, 2008-03-14 at 15:18 +0100, Jochen Theodorou wrote: > > > """ > > foo=null > > def foo=null > > """ > > > > in Groovy this is a legal script. the first line sets the value null for > > "foo" in the binding and the second one defines a local variable, > > But a local variable in what scope. The point being made is that there > is inconsistent manipulation of methods and variables. > > > > meaning that the name foo changes its meaning from this point on. > > Not entirely true. > > foo = 1 > def foo = 2 > println ( foo ) > def c = { println ( foo ) } > c ( ) > def d ( ) { println ( foo ) } > d ( ) > > c and d are at the same scope in this script but the search rules are > totally different. I find this inconsistent and unjustifiable. > > There is no need to repeat why it works this way in Groovy, I know that. > This is a case of finding an argument as to why this is the correct > behaviour in your opinion. My view is that the behaviour is wrong and > should be changed so as to make it consistent from the point of view of > the script as the thing being programmed. I should not have to know how > the script is converted into a class in order to be able to understand > the behaviour. > > > > Indeed, if I would make the def line a field definition, then foo would > > be a reference to the field instead of the binding, thus your "his > > variable is found here" would be right. But think about this: > > That is good then. > > > > """ > > foo=null > > if (true){ > > def foo=null > > } > > """ > > > > what will tis do? In current Groovy the first line will again access the > > binding, the def line will create a local variable, that shadows the > > binding, but only for the time the if-block is processed and only after > > the right side of the declaration is processed... yes, another example > > for what is possible at the moment: > > Why is that wrong? > > > > """ > > foo = 1 > > def foo = foo > > """ > > > > If I change foo to become a field because of the usage of def, then this > > code has to be illegal, while it is currently perfectly legal. > > Why? > > > > So in short, "this variable is found here" does not fit with the concept > > of nested scopes. A change from local variable to field is a major > > change to the semantics at multiple places.. I would not vote for > > putting that into 1.6, not without indicator. > > The current semantics are inconsistent and incomprehensible to anyone > who does not learn the intimate details about how a script is turned > into a class. > > What indicator do you need to make the change? Let me know what the > metric is and I will set about ensuring that it happens. Unless someone > can convince me that the current semantic is the only sane one. > > > > More interesting would be the usage of an annotation to tell the > > compiler that this should be a field/property instead of a local > > variable. This way would compatible with what we have now. > > Why patch a bad situation when you can do a proper fix? > > > > -- > Russel. > ==================================================== > Dr Russel Winder Partner > > Concertant LLP t: +44 20 7193 9203 > 41 Buckmaster Road, f: +44 8700 516 084 > London SW11 1EN, UK. m: +44 7770 465 077 > -- Graeme Rocher Grails Project Lead G2One, Inc. Chief Technology Officer http://www.g2one.com --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
In reply to this post by Russel Winder-2
Russel Winder schrieb:
> On Fri, 2008-03-14 at 15:18 +0100, Jochen Theodorou wrote: > >> """ >> foo=null >> def foo=null >> """ >> >> in Groovy this is a legal script. the first line sets the value null for >> "foo" in the binding and the second one defines a local variable, > > But a local variable in what scope. The point being made is that there > is inconsistent manipulation of methods and variables. What exactly is the inconsistency? the only nested blocks methods can apprea in in Java are class blocks. In a script you have no class block, thus methods can not appear in any block. A declaration is different, thus removing the class context a declaration would normally only indicate a local variable and no field. If you go and say top level variables are fields instead (not also, because there is a huge semantic difference) then you have the separation you wanted, but without the class block indicating the difference. Now any block makes this difference... I think I remember we once had such a scoping in Groovy. And it was horrible. At that time defining a variable at the top level did make the variable appear in the binding, but many people had a problem with variables in a sub block not appearing in the binding. Also that time the question was what happens to variables defined in a method. Some thought they would be global, other thought they would not be.. I think they were... not sure anymore.. I rewrote the whole scoping way before 1.0. I only remember hat many people where confused.. and filled many many bug reports. they should be in JIRA >> meaning that the name foo changes its meaning from this point on. > > Not entirely true. > > foo = 1 > def foo = 2 > println ( foo ) > def c = { println ( foo ) } > c ( ) > def d ( ) { println ( foo ) } > d ( ) > > c and d are at the same scope in this script but the search rules are > totally different. I find this inconsistent and unjustifiable. We do not argue about this being inconsistent, I agree with you here. It is just that I have not seen a better solution yet. Any other solution might solve this problem, but it makes new problems then. > There is no need to repeat why it works this way in Groovy, I know that. > This is a case of finding an argument as to why this is the correct > behaviour in your opinion. My view is that the behaviour is wrong and > should be changed so as to make it consistent from the point of view of > the script as the thing being programmed. I should not have to know how > the script is converted into a class in order to be able to understand > the behaviour. I somehow get the felling you totally ignore explanation two.. >> Indeed, if I would make the def line a field definition, then foo would >> be a reference to the field instead of the binding, thus your "his >> variable is found here" would be right. But think about this: > > That is good then. > >> """ >> foo=null >> if (true){ >> def foo=null >> } >> """ >> >> what will tis do? In current Groovy the first line will again access the >> binding, the def line will create a local variable, that shadows the >> binding, but only for the time the if-block is processed and only after >> the right side of the declaration is processed... yes, another example >> for what is possible at the moment: > > Why is that wrong? I did not say it is wrong, I explained what happens now. changing the semantics of this to letting "def foo" define a field, would mean the outer foo would not write in the binding, but the field. I think that is far from how Groovy behaves in a normal class... too far. >> """ >> foo = 1 >> def foo = foo >> """ >> >> If I change foo to become a field because of the usage of def, then this >> code has to be illegal, while it is currently perfectly legal. > > Why? yes, sorry, my mistake... but still.. what would it do? In current Groovy the first line would access the binding, while the second line would initialize the new local variable foo with the value of foo from the binding. Making foo a field would mean for example that the first foo would access the field instead and the binding would not contain a value named foo anymore. then the next line would set foo with itself... well that is if the field definition is moved outside, but the init expression is not... if that expression is moved too, then foo would still have the value 1, but it would get initialized first with itself. or in other words: """ foo = 1 def foo = foo+1 //assert foo==2 or //assert foo==1 ? """ which one should it be?Not to mention that: """ def foo = foo foo = 1 """ would not run atm (if the binding contains no foo), but with the field it would. It all depends on what exact kind of scoping should be used here. Should the outer filed be made just into a field and the declaration changed into an assignment? Does that apply declarations in blocks too, or not? Or should the field be defined only from the point on the declaration happens? >> So in short, "this variable is found here" does not fit with the concept >> of nested scopes. A change from local variable to field is a major >> change to the semantics at multiple places.. I would not vote for >> putting that into 1.6, not without indicator. uh... where did my "not" go... damn.... not into 1.6 please ;) [...] > What indicator do you need to make the change? a visual clue to the user to make the difference in semantics clear. Classes have the separation between class and method scope. What do have scripts? > Let me know what the > metric is and I will set about ensuring that it happens. Unless someone > can convince me that the current semantic is the only sane one. in an insane world only.... oh, sorry, wrong text ;) If I do a change here then I need a full definition of how it should behave. then we can look at how much it differs from what we currently have in normal classes and what it would mean for scripts. And I need a solution for all these corner cases such as shadowing (fields and binding), where an assignment is legal, if redeclaration is possible or not... and surly much more I didn't think about yet. >> More interesting would be the usage of an annotation to tell the >> compiler that this should be a field/property instead of a local >> variable. This way would compatible with what we have now. > > Why patch a bad situation when you can do a proper fix? that depends on how proper the proper fix is ;) bye blackdrag -- Jochen "blackdrag" Theodorou The Groovy Project Tech Lead (http://groovy.codehaus.org) http://blackdragsview.blogspot.com/ http://www.g2one.com/ --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
In reply to this post by Graeme Rocher
Graeme Rocher schrieb:
> I gotta agree with Russel here, remember he stands to be hit the > hardest by this change as the author of Gant. The fact is the whole > way scoping rules work in Groovy scripts is counter intuitive. Of > course we can try to persuade ourselves that it is this way because of > x,y and z. But really we have to ask ourselves why can't we make it > into something sane? I am all open for discussing a change as long as there is not only an idea, but a real definition of the change and all the semantics that are involved with it. If I would imagine a Groovy script as a language that is more functionally oriented and where a function can not access local states, then what is missing is only something that shows what is local and what is not. And would you want a new keyword for that? A keyword that makes sense only in a script? If you go without a special syntactic clue, then you will still have an insane solution in my eyes. Such a clue could also be class { def foo } in a script. In that case, older scripts wouldn't be touched in their functionality... and no.. I am really not trying to "patch" here. I just think if there is a visual clue needed, then it makes more sense to give this clue to the non local variables instead to the local ones, because one the local ones appear more often and two they appear in nested blocks and three it would mean a fundamental change when you think about normal classes. If there is a solution without a syntactic clue, then define one and we will see...it is just.. the current situation is bad, because we have an ambiguous scope. Exchanging one ambiguous situation with another one seems to be no good solution for me. And for me it seems that the only way to make the situation less ambiguous is by adding a syntactic clue. bye blackdrag -- Jochen "blackdrag" Theodorou The Groovy Project Tech Lead (http://groovy.codehaus.org) http://blackdragsview.blogspot.com/ http://www.g2one.com/ --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
In reply to this post by Russel Winder-2
I've always found the behaviour of scripts annoying. If I had my way the rules would be as follows: 1/ a Script compiles to a Closure (the Binding is the delegate) 2/ a 'method" declaration in a Script compiles to a Closure and the name is a local variable permantently bound to the Closure. 3/ the Binding would *not* return null if it does not already contain the variable. Frankly I'm not enamoured with fact that assigning to an undefined variable puts it in the Binding. I'd prefer this was explicit (binding.x = 1, for example). However we had this arguamnt ages ago and I didn't win. It's probably too late to change this now. John Wilson |
|
In reply to this post by Jochen Theodorou
I haven't used scripts that much, but after reading all the comments on this issue, I do agree with Jochen here. I want to propose 1 change to the way scripts are compiled: could we just disallow local variable defs placed before method defs? This would prevent a lot of surprises during runtime. The compiler could even suggest using a closure. But method defs are still there if people want them. It wouldn't even functionally break any scripts, only syntactically. René de Bloois > -----Original Message----- > From: Jochen Theodorou [mailto:[hidden email]] > Sent: vrijdag 14 maart 2008 07:08 PM > To: [hidden email] > Subject: Re: [groovy-user] script scoping question > > Graeme Rocher schrieb: > > I gotta agree with Russel here, remember he stands to be hit the > > hardest by this change as the author of Gant. The fact is the whole > > way scoping rules work in Groovy scripts is counter intuitive. Of > > course we can try to persuade ourselves that it is this way > because of > > x,y and z. But really we have to ask ourselves why can't we make it > > into something sane? > > I am all open for discussing a change as long as there is not > only an idea, but a real definition of the change and all the > semantics that are involved with it. If I would imagine a > Groovy script as a language that is more functionally > oriented and where a function can not access local states, > then what is missing is only something that shows what is > local and what is not. And would you want a new keyword for > that? A keyword that makes sense only in a script? > > If you go without a special syntactic clue, then you will > still have an insane solution in my eyes. > > Such a clue could also be > > class { > def foo > } > > in a script. In that case, older scripts wouldn't be touched > in their functionality... and no.. I am really not trying to > "patch" here. I just think if there is a visual clue needed, > then it makes more sense to give this clue to the non local > variables instead to the local ones, because one the local > ones appear more often and two they appear in nested blocks > and three it would mean a fundamental change when you think > about normal classes. If there is a solution without a > syntactic clue, then define one and we will see...it is > just.. the current situation is bad, because we have an > ambiguous scope. Exchanging one ambiguous situation with > another one seems to be no good solution for me. And for me > it seems that the only way to make the situation less > ambiguous is by adding a syntactic clue. > > bye blackdrag > > -- > Jochen "blackdrag" Theodorou > The Groovy Project Tech Lead (http://groovy.codehaus.org) > http://blackdragsview.blogspot.com/ > http://www.g2one.com/ > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > > > > This e-mail and any attachment is for authorised use by the intended recipient(s) only. It may contain proprietary material, confidential information and/or be subject to legal privilege. It should not be copied, disclosed to, retained or used by, any other party. If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender. Thank you. --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
| Powered by Nabble | See how NAML generates this page |
