script scoping question

classic Classic list List threaded Threaded
20 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

script scoping question

Danno Ferrin
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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

Pascal DeMilly (Groovy)

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.

signature.asc (196 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

Jochen Theodorou
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


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

Danno Ferrin


On 3/13/08, Jochen Theodorou <[hidden email]> wrote:
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




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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

Jochen Theodorou
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


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

Danno Ferrin


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?


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
"""

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
the def indicates that, then it is very weak.

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
that the def indicates that a local variable is declared. At last this
one is consistent unless you are in a class body.

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
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.

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
that...

"""
   def m(){foo}
   foo="a"
   assert m()=="a"
   def foo="b"
   assert m()=="b"
"""

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
will fail. If we say "def foo" creates a field, then the first assert
will fail.

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:

"""
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:

Similarly it fails in Java, we should leave that part as is.

"""
if (true) {
   def foo=null
}
def foo=null
"""

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

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
> 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.

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
> 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
"""

------------------------------------------------------
I'm Danno Ferrin, and I approved this message.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

Russel Winder-2
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()
>    }
> }
This code transformation has always struck me as wrong.  If the 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

signature.asc (196 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

Russel Winder-2
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()
>    }
> }
This would have been my choice of semantics.

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

signature.asc (196 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

Russel Winder-2
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...
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.

[ . . . ]

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

signature.asc (196 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

Jochen Theodorou
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


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

Jochen Theodorou
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


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

Jochen Theodorou
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


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

Russel Winder-2
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:
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

signature.asc (196 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

Danno Ferrin
In reply to this post by Jochen Theodorou
On 3/14/08, Jochen Theodorou <[hidden email]> wrote:
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.


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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

Danno Ferrin
In reply to this post by Jochen Theodorou

>      > (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?


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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

Graeme Rocher
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


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

Jochen Theodorou
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


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

Jochen Theodorou
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


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: script scoping question

tugwilson
In reply to this post by Russel Winder-2

Russel Winder-4 wrote
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...

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.
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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

RE: script scoping question

Bloois, Rene de
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


Loading...