Re: Defining a global variable

2020-10-23 Thread Anton Shepelev
Merlin Beedell:

> I sure wish the word 'global' was used instead of
> 'static'.  It just kinda makes more sense to me!

Those are orthogonal concepts.  `static' denotes an element
whose existance is with the program, and `dynamic' -- an
element whose existance is with an instance of a dymamic
object. `global' denotes an element that is accessible from
all over a program unit (which may be module, class,
namespace, or entire program), and `local` denotes an
element owned by, accessible from within, a program unit.
The local/global dichotomy is relative: a variable may be
global to a method, but local to the class.  Fields in OOP
are local with respect to the containing class, but gloal
with respect to the methods, which is why I so dislike them.

Hold on, MG, I have not forgotten about your e-mail.



Re: Defining a global variable

2020-10-21 Thread MG

Hi Merlin,

I don't know how your reply pertains to what I said, but generally 
speaking having implicit variables is imho generally a very poor design 
choice, as anyone who has experienced them in e.g. a Basic dialect will 
be able to confirm, simply because one innocuous typo can introduce a 
hard to track bug into your code, by implicitly defining a new variable 
instead of modifying an existing one.


Cheers,
mg


On 21/10/2020 17:46, Merlin Beedell wrote:

I thought that implicit variables would overcome this.  Not an elegant solution 
- as you are simply declaring variables on the fly without an explicit data 
type or even a 'def'.
Having said, it is generally safer to explicitly list the parameters used in a 
method when used in this context (e.g. in a script without an explicit class 
declaration to mop up this case).
And as for 'global' - I sure wish the word 'global' was used instead of 
'static'.  It just kinda makes more sense to me!
//===
test=''  //implicit declaration of a variable
void func()
{
   println(test)
}
test = 'hello'
func()
//===

Or just

//===
void func()
{
   println(test)
}
test = 'hello'
func()
//===

Merlin Beedell
-Original Message-
From: MG 
Sent: 15 October 2020 6:21 PM
To: users@groovy.apache.org; Jochen Theodorou 
Subject: Re: Defining a global variable

On 15/10/2020 18:27, Jochen Theodorou wrote:

well.. even scripts are first compiled into a class before the class
is then executed. Groovy has no interpreter

Which, I think, is a lesser known fact, and quite surprising to people who perceive 
Groovy just under its "script language" aspect ;-)






RE: Defining a global variable

2020-10-21 Thread Merlin Beedell
I thought that implicit variables would overcome this.  Not an elegant solution 
- as you are simply declaring variables on the fly without an explicit data 
type or even a 'def'.
Having said, it is generally safer to explicitly list the parameters used in a 
method when used in this context (e.g. in a script without an explicit class 
declaration to mop up this case).
And as for 'global' - I sure wish the word 'global' was used instead of 
'static'.  It just kinda makes more sense to me!
//===
   test=''  //implicit declaration of a variable
   void func()
   {
  println(test)
   }
   test = 'hello'
   func()
//===

Or just

//===
   void func()
   {
  println(test)
   }
   test = 'hello'
   func()  
//===

Merlin Beedell 
-Original Message-
From: MG  
Sent: 15 October 2020 6:21 PM
To: users@groovy.apache.org; Jochen Theodorou 
Subject: Re: Defining a global variable

On 15/10/2020 18:27, Jochen Theodorou wrote:
> well.. even scripts are first compiled into a class before the class 
> is then executed. Groovy has no interpreter

Which, I think, is a lesser known fact, and quite surprising to people who 
perceive Groovy just under its "script language" aspect ;-)




Re: Defining a global variable

2020-10-15 Thread MG

On 15/10/2020 18:27, Jochen Theodorou wrote:

well.. even scripts are first compiled into a class before the class is
then executed. Groovy has no interpreter


Which, I think, is a lesser known fact, and quite surprising to people 
who perceive Groovy just under its "script language" aspect ;-)





Re: Defining a global variable

2020-10-15 Thread Jochen Theodorou

On 15.10.20 12:16, Anton Shepelev wrote:

Jochen Theodorou to Anton Shepelev:


Jochen Theodorou:


Frankly... for years we have been defending this
position, but now, with so much distance I actually
really wonder why we keep this.


Perhaps it would have helped if you had documented not
only language features but also their rationale
(justification), at least is difficult, debatable cases.


the reason is easy: it reflects the implementation. But
the implementation can be changed


The implementation reflects the implementation? I do not
understand.


specification by implementation I mean

[...]

Whereas methods are also code, I believe it would be much
clearer if it said "immediate code" -- code that is executed
immediately rather than compiled into a callable method.


well.. even scripts are first compiled into a class before the class is
then executed. Groovy has no interpreter

[...]

I am not sure, but we both failed to find that paragraph
until Maarten pointed it out. But now that I think about it
again, it is the right place.


I was searching for something different. A more high-level description
of variable scopes and how they work instead of describing the specific
case of a script with the common base class.

bye Jochen




Re: Defining a global variable

2020-10-14 Thread Jochen Theodorou

On 14.10.20 17:01, Anton Shepelev wrote:

Jochen Theodorou to Anton Shepelev:

[...]

Frankly... for years we have been defending this position,
but now, with so much distance I actually really wonder
why we keep this.


Perhaps it would have helped if you had documented not only
language features but also their rationale (justification),
at least is difficult, debatable cases.


the reason is easy: it reflects the implementation. But the
implementation can be changed

[...]

it is actually less the assignment operator itself, it is
the effect of scopes of dynamic variables. To compare.. in
Java you have a static scope for a variable.


But I do not know Java and am learning Groovy as a stand-
alone language, not as a Java derivative.


Sure, any other language you know ;) Python for example has a different
variable scoping system. But most static languages have something like
those static variable scopes.


The compiler knows at any time where a variable is
declared, and where to write it to (local variable or
class). In Groovy we also have the static variable scopes,
but they are "extended" in dynamic Groovy with dynamic
variables. This means the (meta) class is "asked" for the
value and existence of a variable at runtime as soon as we
leave the static scope.


Somewhat similar to metatables in Lua, isn't it?


I never worked with Lua, but from what I have seen I would answer yes.


Why does
not the same thing work from class methods, even from static
class methods? --

class Boo {
static def boo()
{x = 1
}
}


It does work, only a class does not have the special implementation
Script has.


class AlwaysAnswer{
  def getProperty(String something){ 42 }
  def ask(question){ return answer }
}

def alwaysAnswer = new AlwaysAnswer()
assert alwaysAnswer.answerToMeaningOfLife == 42
assert alwaysAnswer.myName == 42
assert alwaysAnswer.ask("Are you kidding me?") == 42


The class AlwaysAnswer is a real class and exists additionally to the
class we generate for the script itself. You will see that the code
above does not throw any exception, that is because I implemented the
getProperty method, which is used by the meta class system to answer
when asked for an unknown property. For a static method/property we have
something too:
https://docs.groovy-lang.org/latest/html/documentation/core-metaprogramming.html#_static_propertymissing

If you look at
https://github.com/apache/groovy/blob/master/src/main/java/groovy/lang/Script.java#L54
you see that the class Script does implement getProperty method. Script
is normally used as base class for all Groovy scripts. My example above
for example will generate code like this:


class AlwaysAnswer{
  def propertyMissing(String something){ 42 }
  def ask(question){ return answer }
}

class Scrip1243324 extends groovy.lang.Script{
  void run() {
 def alwaysAnswer = new AlwaysAnswer()
 assert alwaysAnswer.answerToMeaningOfLife == 42
 assert alwaysAnswer.myName == 42
 assert alwaysAnswer.ask("Are you kidding me?") == 42
  }
}


It is now possible to let the Groovy compiler use a different base class
for scripts, in which case the runtime behaviour changes and you could
let it disallow those global variables - or allow read before write. Or
the script defines overwrites the getProperty method and defines this
kind of behaviour itself.

[...]

In another reply, Maarten Boekhold refers to section 3.4
(Variables) of the "Program structure" document, which has
the following to say about assignments to undeclared (or
undefined?) variables:

if the variable is undeclared, it goes into the script
binding. The binding is visible from the methods, and is
especially important if you use a script to interact with
an application and need to share data between the script
and the application.


I think you should read the whole chapter 3
http://groovy-lang.org/structure.html#_scripts_versus_classes Otherwise
you miss out on some of the concepts and I think this passage alone then
makes much less sense. On the other hand Maarten really explain most of
that already in his mail


The explanation is OK, but I failed to look into that
document. Do you think you can provide better documentation
at a better place? If so, I should certainly appreciate it.
I also thank Maarten for reply.


A better place? What was wrong?

bye Jochen



Re: Defining a global variable

2020-10-14 Thread Anton Shepelev
Jochen Theodorou to Anton Shepelev:

> > String test
> >
> > void func()
> > {
> >println(test)
> > }
> >
> > test = 'hello'
> > func()
> >
> > Why, then, is `test' inaccessible from the function in
> > my script?
>
> because the method you defined is not nested in another
> method, instead it exists parallel to the other method
> that represents your script body, and they do not share
> local variables.

Thanks for the explanation, Jochen.

> Frankly... for years we have been defending this position,
> but now, with so much distance I actually really wonder
> why we keep this.

Perhaps it would have helped if you had documented not only
language features but also their rationale (justification),
at least is difficult, debatable cases.

> It comes up as a problem on a regular base, but wouldn't
> be so hard to "fix" really. I mean it is not broken, it
> works as designed, just not very intuitive.

Now that I know the answer, I am not sure the behavior
should be changed: the must be a way to dictinguish between
local variables of the `run' method, the class fields, and
the binding variables.

> it is actually less the assignment operator itself, it is
> the effect of scopes of dynamic variables. To compare.. in
> Java you have a static scope for a variable.

But I do not know Java and am learning Groovy as a stand-
alone language, not as a Java derivative.

> The compiler knows at any time where a variable is
> declared, and where to write it to (local variable or
> class). In Groovy we also have the static variable scopes,
> but they are "extended" in dynamic Groovy with dynamic
> variables. This means the (meta) class is "asked" for the
> value and existence of a variable at runtime as soon as we
> leave the static scope.

Somewhat similar to metatables in Lua, isn't it?  Why does
not the same thing work from class methods, even from static
class methods? --

   class Boo {
   static def boo()
   {x = 1
   }
   }

> I would have loved to point to our documentation for this,
> but I actually am unable to find this there.

In another reply, Maarten Boekhold refers to section 3.4
(Variables) of the "Program structure" document, which has
the following to say about assignments to undeclared (or
undefined?) variables:

   if the variable is undeclared, it goes into the script
   binding. The binding is visible from the methods, and is
   especially important if you use a script to interact with
   an application and need to share data between the script
   and the application.

The explanation is OK, but I failed to look into that
document. Do you think you can provide better documentation
at a better place? If so, I should certainly appreciate it.
I also thank Maarten for reply.



Re: Defining a global variable

2020-10-14 Thread Maarten Boekhold

Hi,

I've been caught out by this in the past as well. It's actually quite
simple...

A Groovy Script like:

   String test

   void func(){
    println(test)
   }

   test = 'hello'
   func()

Gets compiled to a class as:

   class MyScript extends Script {
    def run() {
        String test

        test = 'hello'
        func()
    }

    void func() {
        println(test)
    }
   }

All "lose code" gets collected into the run() method, and functions
defined in your script are copied into the class as methods. As you can
see, the declaration "String test" ends up as part of the run() method,
and therefore the "test" variable is scoped locally to that run()
method. It's not a class member. Your func() method is not able to see it.

You can work around that by annotating the "String test" declaration
with the @Field annotation:

   @Field String test

   void func() {
    println(test)
   }

   test = 'hello'
   func()

This will cause the "String test" declaration to be included in the
Script class as a class member:

   class MyScript extends Script {
    String test

    def run() {
        test = 'hello'
        func()
    }

    void func(){
        println(test)
    }
   }

This is described in
https://docs.groovy-lang.org/latest/html/documentation/core-metaprogramming.html#xform-Field.
It is also very lightly mentioned in
https://groovy-lang.org/structure.html#_variables, but that page
probably doesn't make it clear enough.

Maarten

On 14/10/2020 15:45, Anton Shepelev wrote:

Hello, all

I tried to define a global variable in a Groovy script.
Section 1.1. of the "Semantics" documents says that one way
to define a variable is via its type, so I defined one in
the global scope of my script:

String test

void func()
{
   println(test)
}

test = 'hello'
func()

but it failed with the error: "No such property: test for
class: Script1". That didn't explain to me what the problem
was, but I learned that the script was looking for a
property named `test' in the global autogenerated Script
class. OK, thought I, I will give it what it asks, and
cosulted section 1.6.2. (Properties) of the "Object
orientation" document, which told me that the definition of
a property is identical to the definition of a variable I
used above, i.e. that

String test

defienes a string property `test' or a string variable
`test', depending on context. I was now stuck and resorted
to an internet search, which brought up the following page

Groovy Variable Scope:
https://www.baeldung.com/groovy/variable-scope

where I read:

Scopes in Groovy follow, above all, the rule that all
variables are created public by default. This means that,
unless specified, we'll be able to access any variable we
created from any other scope in the code.

Why, then, is `test' inaccessible from the function in my
script?  And below:

The easiest way to create a global variable in a Groovy
script is to assign it anywhere in the script without any
special keywords. We don't even need to define the type:

   x = 200

After I removed the "String test" line from my script it
started to work, but why?  I returned to the "Semantics"
document and read section 1.2. (Variable assignment) to see
whether the assignment operator may have the side effect of
defining a missing variable, but there is no indication that
it has.

Can you please explain to me, preferable with the
correspoding references to official documentation, why my
scirpt does not work whereas the modified one does?



Re: Defining a global variable

2020-10-14 Thread Jochen Theodorou

On 14.10.20 13:45, Anton Shepelev wrote:
[...]

String test

defienes a string property `test' or a string variable
`test', depending on context.


the context here is that of a method, so it is a local variable


I was now stuck and resorted
to an internet search, which brought up the following page

Groovy Variable Scope:
https://www.baeldung.com/groovy/variable-scope

where I read:

Scopes in Groovy follow, above all, the rule that all
variables are created public by default. This means that,
unless specified, we'll be able to access any variable we
created from any other scope in the code.

Why, then, is `test' inaccessible from the function in my
script?


because the method you defined is not nested in another method, instead
it exists parallel to the other method that represents your script body,
and they do not share local variables. Frankly... for years we have been
defending this position, but now, with so much distance I actually
really wonder why we keep this. It comes up as a problem on a regular
base, but wouldn't be so hard to "fix" really. I mean it is not broken,
it works as designed, just not very intuitive.


 And below:

The easiest way to create a global variable in a Groovy
script is to assign it anywhere in the script without any
special keywords. We don't even need to define the type:

   x = 200

After I removed the "String test" line from my script it
started to work, but why?


without the declaration you are writing to a outer scope variable, which
in case of a script usually ends up in the binding. A variable in the
binding of a script is defined by writing it. Reading a non-existent
variable would cause an error.


I returned to the "Semantics"
document and read section 1.2. (Variable assignment) to see
whether the assignment operator may have the side effect of
defining a missing variable, but there is no indication that
it has.


it is actually less the assignment operator itself, it is the effect of
scopes of dynamic variables. To compare.. in Java you have a static
scope for a variable. The compiler knows at any time where a variable is
declared, and where to write it to (local variable or class). In Groovy
we also have the static variable scopes, but they are "extended" in
dynamic Groovy with dynamic variables. This means the (meta) class is
"asked" for the value and existence of a variable at runtime as soon as
we leave the static scope. In Java leaving the static scope would mean
an compilation error. But in Groovy we are then using the MOP to find
meaning in what is requested. In case of a Closure this results in
checking the enclosed scope for the value of a variable. In case of a
class this results in set/getProperty and similar methods being called
as part of the MOP. A Groovy script is a class too, only that its
getProperty method checks the binding for the value and setProperty
writes it. There is no formal way to declare a variable in a binding, it
is solely defined by the program writing it. As such it has no static
type (as all dynamic variables).

I would have loved to point to our documentation for this, but I
actually am unable to find this there. I actually thought I have written
something years ago (back when it was still codehaus), but I cannot find
any trace of that either I guess I should really get used to write
everything I write for a project also on my blog, so that I can have at
least one original reference. So no references I am aware of, sorry

bye Jochen