[groovy-jsr] Categories and Closures

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

[groovy-jsr] Categories and Closures

Ray Cromwell

The following example doesn't work (MissingMethodException), but this
seems to violate both the principle of least surprise and the basic
definition of a closure (closed over all free variables, bound variables
must survive loss of the context in which the closure was defined)


class cat
{
   static String xyz(String s) { return "xyz"+s }
}

def c
use(cat)
{
   c={ print it.xyz() }

}

c("Hello World")

Although you could argue that this is a method binding, one could
replace the category with a getXyz() and bind the closure to the
variable "it.xyz" instead. Either way, I feel that the closure should be
closed over all free variables, including meta/pseudo-variables and
methods which are created by categories.


IMHO, the closure should execute regardless of the context in which it
is executed. That means that compiled closures should have some idea of
the scope of categories that existed when they were created.

-Ray





---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

RE: [groovy-jsr] Categories and Closures

Dierk König
It is by design that outside the 'use' closure, the category
methods are not available.

cheers
Mittie

> -----Original Message-----
> From: news [mailto:[hidden email]]On Behalf Of Ray Cromwell
> Sent: Montag, 29. Mai 2006 9:59
> To: [hidden email]
> Subject: [groovy-jsr] Categories and Closures
>
>
>
> The following example doesn't work (MissingMethodException), but this
> seems to violate both the principle of least surprise and the basic
> definition of a closure (closed over all free variables, bound variables
> must survive loss of the context in which the closure was defined)
>
>
> class cat
> {
>    static String xyz(String s) { return "xyz"+s }
> }
>
> def c
> use(cat)
> {
>    c={ print it.xyz() }
>
> }
>
> c("Hello World")
>
> Although you could argue that this is a method binding, one could
> replace the category with a getXyz() and bind the closure to the
> variable "it.xyz" instead. Either way, I feel that the closure should be
> closed over all free variables, including meta/pseudo-variables and
> methods which are created by categories.
>
>
> IMHO, the closure should execute regardless of the context in which it
> is executed. That means that compiled closures should have some idea of
> the scope of categories that existed when they were created.
>
> -Ray
>
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list please visit:
>
>     http://xircles.codehaus.org/manage_email

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

[groovy-jsr] Re: Categories and Closures

Ray Cromwell
Dierk Koenig wrote:
> It is by design that outside the 'use' closure, the category
> methods are not available.
>

   And what is the reasoning for this design? The fact that a bound
variable can disappear after you go out of scope rubs me the wrong way.
I find this behavior "surprising".


---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

RE: [groovy-jsr] Re: Categories and Closures

Dierk König
Categories have a cross-cutting nature like AOP.
This can potentially cut deeper and wider than you whish.
To safeguard from that danger, the effect is limited to the
execution of the closure that is send to the use(cat) method.

I don't understand why you think this would have anyhing
to do with binding variables. Remember that reference resolution
happens at runtime.

cheers
Mittie


> -----Original Message-----
> From: news [mailto:[hidden email]]On Behalf Of Ray Cromwell
> Sent: Montag, 29. Mai 2006 10:15
> To: [hidden email]
> Subject: [groovy-jsr] Re: Categories and Closures
>
>
> Dierk Koenig wrote:
> > It is by design that outside the 'use' closure, the category
> > methods are not available.
> >
>
>    And what is the reasoning for this design? The fact that a bound
> variable can disappear after you go out of scope rubs me the wrong way.
> I find this behavior "surprising".
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list please visit:
>
>     http://xircles.codehaus.org/manage_email

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

[groovy-jsr] Re: Categories and Closures

Ray Cromwell

Because it can lead to hard to track down bugs. A closure is
traditionally self contained and does not depend on calling context for
its environment except for parameter arguments.

Now according to your design, it happens that closures returned from
methods, possibly deep within a library module, may or may not execute
properly, unless clear documentation warns you to use the proper
category. This makes closures less portable.

Dierk Koenig wrote:
> Categories have a cross-cutting nature like AOP.
> This can potentially cut deeper and wider than you whish.
> To safeguard from that danger, the effect is limited to the
> execution of the closure that is send to the use(cat) method.
>
> I don't understand why you think this would have anyhing
> to do with binding variables. Remember that reference resolution
> happens at runtime.


mymethod()
{
   def c
   use(foo)
   {
     def someobject=...
     c = {  someobject.xxx + 10 }
   }

   return c
}

Now, c.call() works if 'xxx' is a property of 'someobject', and fails if
'xxx' is a property supplied by 'foo' I don't know what your definition
of "variable binding" is, but mine says that 'xxx' is not a free
variable, but bound to someobject, which is a local variable (reference
to heap allocated possibly) of method 'mymethod' The fact that it is
resolved at runtime has little to do with the definition of "free" vs
"bound" variable.

I don't want to get into a fight over semantics and word play however,
since it detracts from the overall point, which is the design as it is,
could lead to some surprising bugs to people in large codebases if
closures and other high order functions are passed around that are
created within 'use' scopes.

At the very least, the closure should capture the categories in which it
was defined, and allow them to be later "overriden" if you want by
another use scope. But the way it stands now, I think it the
implementation violates what many people will think of as closure semantics.



> cheers
> Mittie
>
>
>
>>-----Original Message-----
>>From: news [mailto:[hidden email]]On Behalf Of Ray Cromwell
>>Sent: Montag, 29. Mai 2006 10:15
>>To: [hidden email]
>>Subject: [groovy-jsr] Re: Categories and Closures
>>
>>
>>Dierk Koenig wrote:
>>
>>>It is by design that outside the 'use' closure, the category
>>>methods are not available.
>>>
>>
>>   And what is the reasoning for this design? The fact that a bound
>>variable can disappear after you go out of scope rubs me the wrong way.
>>I find this behavior "surprising".
>>
>>
>>---------------------------------------------------------------------
>>To unsubscribe from this list please visit:
>>
>>    http://xircles.codehaus.org/manage_email
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list please visit:
>
>     http://xircles.codehaus.org/manage_email
>
>


---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

[groovy-jsr] Re: Categories and Closures

Ray Cromwell
In reply to this post by Dierk König


BTW, before this turns into a huge debate, I have no problem leaving the
design as is, but I think this needs to be documented, since IMHO it is
"surprising", and warn programmers of idioms that could lead to buggy or
surprising behavior if you don't know what you're doing.


---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

RE: [groovy-jsr] Re: Categories and Closures

Dierk König
In reply to this post by Ray Cromwell
This hasn't really much to do with closures.

The design of how to use Categories applies equally to every
code, be it closures, methods, scripts, builders, whatever.

If your code relies on a certain context which is not there
at execution time, you'll get an error.

Interestingly enough, you don't even have to define your
closure inside the category:

----
class Cat
{
   static String xyz(String s) { return "xyz"+s }
}

def c = { print it.xyz() }

use(Cat)
{
   c("Hello World")
}
----

BTW: this is more a discussion for the groovy-user list.

cheers
Mittie

P.S. The forthcoming Groovy in Action book contains the
probably best documentation of that topic:
http://groovy.canoo.com/gina


> -----Original Message-----
> From: news [mailto:[hidden email]]On Behalf Of Ray Cromwell
> Sent: Montag, 29. Mai 2006 10:55
> To: [hidden email]
> Subject: [groovy-jsr] Re: Categories and Closures
>
>
>
> Because it can lead to hard to track down bugs. A closure is
> traditionally self contained and does not depend on calling context for
> its environment except for parameter arguments.
>
> Now according to your design, it happens that closures returned from
> methods, possibly deep within a library module, may or may not execute
> properly, unless clear documentation warns you to use the proper
> category. This makes closures less portable.
>
> Dierk Koenig wrote:
> > Categories have a cross-cutting nature like AOP.
> > This can potentially cut deeper and wider than you whish.
> > To safeguard from that danger, the effect is limited to the
> > execution of the closure that is send to the use(cat) method.
> >
> > I don't understand why you think this would have anyhing
> > to do with binding variables. Remember that reference resolution
> > happens at runtime.
>
>
> mymethod()
> {
>    def c
>    use(foo)
>    {
>      def someobject=...
>      c = {  someobject.xxx + 10 }
>    }
>
>    return c
> }
>
> Now, c.call() works if 'xxx' is a property of 'someobject', and fails if
> 'xxx' is a property supplied by 'foo' I don't know what your definition
> of "variable binding" is, but mine says that 'xxx' is not a free
> variable, but bound to someobject, which is a local variable (reference
> to heap allocated possibly) of method 'mymethod' The fact that it is
> resolved at runtime has little to do with the definition of "free" vs
> "bound" variable.
>
> I don't want to get into a fight over semantics and word play however,
> since it detracts from the overall point, which is the design as it is,
> could lead to some surprising bugs to people in large codebases if
> closures and other high order functions are passed around that are
> created within 'use' scopes.
>
> At the very least, the closure should capture the categories in which it
> was defined, and allow them to be later "overriden" if you want by
> another use scope. But the way it stands now, I think it the
> implementation violates what many people will think of as closure
> semantics.
>
>
>
> > cheers
> > Mittie
> >
> >
> >
> >>-----Original Message-----
> >>From: news [mailto:[hidden email]]On Behalf Of Ray Cromwell
> >>Sent: Montag, 29. Mai 2006 10:15
> >>To: [hidden email]
> >>Subject: [groovy-jsr] Re: Categories and Closures
> >>
> >>
> >>Dierk Koenig wrote:
> >>
> >>>It is by design that outside the 'use' closure, the category
> >>>methods are not available.
> >>>
> >>
> >>   And what is the reasoning for this design? The fact that a bound
> >>variable can disappear after you go out of scope rubs me the wrong way.
> >>I find this behavior "surprising".
> >>
> >>
> >>---------------------------------------------------------------------
> >>To unsubscribe from this list please visit:
> >>
> >>    http://xircles.codehaus.org/manage_email
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe from this list please visit:
> >
> >     http://xircles.codehaus.org/manage_email
> >
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list please visit:
>
>     http://xircles.codehaus.org/manage_email


---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: [groovy-jsr] Categories and Closures

Jochen Theodorou
In reply to this post by Ray Cromwell
Ray Cromwell schrieb:

>
> The following example doesn't work (MissingMethodException), but this
> seems to violate both the principle of least surprise and the basic
> definition of a closure (closed over all free variables, bound variables
> must survive loss of the context in which the closure was defined)
>
> class cat
> {
>   static String xyz(String s) { return "xyz"+s }
> }
>
> def c
> use(cat)
> {
>   c={ print it.xyz() }
>
> }
>
> c("Hello World")
 >
 > Although you could argue that this is a method binding, one could
 > replace the category with a getXyz() and bind the closure to the
 > variable "it.xyz" instead. Either way, I feel that the closure should
 > be closed over all free variables, including meta/pseudo-variables and
 > methods which are created by categories.

xyz is no variable, it is a method call on the variable it. If your
cahnge it to a getter, then it may be seen as property of "it", but it
is still no real variable. Groovy closires are closing only about local
variables and class members, that are can be called using "this."

> IMHO, the closure should execute regardless of the context in which it
> is executed. That means that compiled closures should have some idea of
> the scope of categories that existed when they were created.

I know, the use-mechanism is insufficient. for example if you use the
closure in a use block but you leave the Thread, then it may happen that
the category won't work too. Currently there is no category scope. We
are planing to change this all, but since we haven't found a good
solution it won't go in 1.0

bye blackdrag

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

RE: [groovy-jsr] Re: Categories and Closures

Dierk König
In reply to this post by Dierk König
If you want your closure using the category without the
need to have the caller of the closure being aware of it
you can do
----
class Cat
{
   static String xyz(String s) { return "xyz"+s }
}

def c = {s ->  use(Cat) { print s.xyz() } }

c("Hello World")
----

cheers
Mittie

> -----Original Message-----
> From: Dierk Koenig [mailto:[hidden email]]
> Sent: Montag, 29. Mai 2006 11:44
> To: [hidden email]
> Subject: RE: [groovy-jsr] Re: Categories and Closures
>
>
> This hasn't really much to do with closures.
>
> The design of how to use Categories applies equally to every
> code, be it closures, methods, scripts, builders, whatever.
>
> If your code relies on a certain context which is not there
> at execution time, you'll get an error.
>
> Interestingly enough, you don't even have to define your
> closure inside the category:
>
> ----
> class Cat
> {
>    static String xyz(String s) { return "xyz"+s }
> }
>
> def c = { print it.xyz() }
>
> use(Cat)
> {
>    c("Hello World")
> }
> ----
>
> BTW: this is more a discussion for the groovy-user list.
>
> cheers
> Mittie
>
> P.S. The forthcoming Groovy in Action book contains the
> probably best documentation of that topic:
> http://groovy.canoo.com/gina
>
>
> > -----Original Message-----
> > From: news [mailto:[hidden email]]On Behalf Of Ray Cromwell
> > Sent: Montag, 29. Mai 2006 10:55
> > To: [hidden email]
> > Subject: [groovy-jsr] Re: Categories and Closures
> >
> >
> >
> > Because it can lead to hard to track down bugs. A closure is
> > traditionally self contained and does not depend on calling context for
> > its environment except for parameter arguments.
> >
> > Now according to your design, it happens that closures returned from
> > methods, possibly deep within a library module, may or may not execute
> > properly, unless clear documentation warns you to use the proper
> > category. This makes closures less portable.
> >
> > Dierk Koenig wrote:
> > > Categories have a cross-cutting nature like AOP.
> > > This can potentially cut deeper and wider than you whish.
> > > To safeguard from that danger, the effect is limited to the
> > > execution of the closure that is send to the use(cat) method.
> > >
> > > I don't understand why you think this would have anyhing
> > > to do with binding variables. Remember that reference resolution
> > > happens at runtime.
> >
> >
> > mymethod()
> > {
> >    def c
> >    use(foo)
> >    {
> >      def someobject=...
> >      c = {  someobject.xxx + 10 }
> >    }
> >
> >    return c
> > }
> >
> > Now, c.call() works if 'xxx' is a property of 'someobject', and fails if
> > 'xxx' is a property supplied by 'foo' I don't know what your definition
> > of "variable binding" is, but mine says that 'xxx' is not a free
> > variable, but bound to someobject, which is a local variable (reference
> > to heap allocated possibly) of method 'mymethod' The fact that it is
> > resolved at runtime has little to do with the definition of "free" vs
> > "bound" variable.
> >
> > I don't want to get into a fight over semantics and word play however,
> > since it detracts from the overall point, which is the design as it is,
> > could lead to some surprising bugs to people in large codebases if
> > closures and other high order functions are passed around that are
> > created within 'use' scopes.
> >
> > At the very least, the closure should capture the categories in which it
> > was defined, and allow them to be later "overriden" if you want by
> > another use scope. But the way it stands now, I think it the
> > implementation violates what many people will think of as closure
> > semantics.
> >
> >
> >
> > > cheers
> > > Mittie
> > >
> > >
> > >
> > >>-----Original Message-----
> > >>From: news [mailto:[hidden email]]On Behalf Of Ray Cromwell
> > >>Sent: Montag, 29. Mai 2006 10:15
> > >>To: [hidden email]
> > >>Subject: [groovy-jsr] Re: Categories and Closures
> > >>
> > >>
> > >>Dierk Koenig wrote:
> > >>
> > >>>It is by design that outside the 'use' closure, the category
> > >>>methods are not available.
> > >>>
> > >>
> > >>   And what is the reasoning for this design? The fact that a bound
> > >>variable can disappear after you go out of scope rubs me the
> wrong way.
> > >>I find this behavior "surprising".
> > >>
> > >>
> > >>---------------------------------------------------------------------
> > >>To unsubscribe from this list please visit:
> > >>
> > >>    http://xircles.codehaus.org/manage_email
> > >
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe from this list please visit:
> > >
> > >     http://xircles.codehaus.org/manage_email
> > >
> > >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe from this list please visit:
> >
> >     http://xircles.codehaus.org/manage_email
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list please visit:
>
>     http://xircles.codehaus.org/manage_email


---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: [groovy-jsr] Categories and Closures

Eric Armstrong-2
In reply to this post by Ray Cromwell
I seem to be on the mailing list for this thread, although
I unsubscribed months ago.


Ray Cromwell wrote:

>
> The following example doesn't work (MissingMethodException), but this
> seems to violate both the principle of least surprise and the basic
> definition of a closure (closed over all free variables, bound variables
> must survive loss of the context in which the closure was defined)
>
>
> class cat
> {
>   static String xyz(String s) { return "xyz"+s }
> }
>
> def c
> use(cat)
> {
>   c={ print it.xyz() }
>
> }
>
> c("Hello World")
>
> Although you could argue that this is a method binding, one could
> replace the category with a getXyz() and bind the closure to the
> variable "it.xyz" instead. Either way, I feel that the closure should be
> closed over all free variables, including meta/pseudo-variables and
> methods which are created by categories.
>
>
> IMHO, the closure should execute regardless of the context in which it
> is executed. That means that compiled closures should have some idea of
> the scope of categories that existed when they were created.
>
> -Ray
>
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list please visit:
>
>    http://xircles.codehaus.org/manage_email
>

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email