Re: Small survey on the usage of the metaclass system and MOP

2024-01-08 Thread Jochen Theodorou

On 08.01.24 20:42, OCsite wrote:
[...]> - the extension class list is collected compile-time and (eventually

when my build script creates the application) automatically added to the
/org.codehaus.groovy.runtime.ExtensionModule/ manifest, so that they
just-work without any extra ado.


So your variant is a clever way to use extension modules. You are not
using categories at all. That's good.


(2) per instance meta classes
https://groovy-lang.org/metaprogramming.html#_per_instance_metaclass
shows examples here
Anyone using that?


Can't recall I ever needed that.


mocking and maybe some special kind of debugging are the only uses-cases
I found so far.


(3) Custom meta class
Anyway trying to force the usage of something else then MetaClassImpl
for the meta class?


Well sort of, though a pretty trivial one. My goal is to get rid of
NPEs; in my personal opinion that darned thing is a proper disaster and
the right behaviour is a completely consistent /null/-propagation
(essentially what Groovy calls a “safe dispatch”). Among many other
things, what I do is

===

def mc=new OCSNMC(org.codehaus.groovy.runtime.NullObject)

         mc.initialize()

         org.codehaus.groovy.runtime.NullObject.metaClass=mc

... ...

}

class OCSNMC extends DelegatingMetaClass {

     OCSNMC(Class clazz){

super(clazz)

     }

     Object invokeMethod(Object object, String methodName, Object[]
arguments) {

if (arguments.size()==1 && methodName=='is') return arguments[0]==null

if (arguments.size()==0 && methodName=='iterator') return [].iterator()

if (arguments.size()==0 && methodName=='hasZeroValue') return YES

null

     }

// alas, does not seem to work for getProperty; that one must be
supported by ASTTs

}

===

Aside that, not sure if interesting to you, but I install my own methods
into metaclasses all the time, like e.g.,

===

         NSMutableDictionary.metaClass.putAt<<{ key,value ->

if(value==nil) delegate.removeObjectForKey(key)

else delegate.setObjectForKey(value,key)

}

         ...

         NSKeyValueCoding.NullValue.class.metaClass.asBoolean={ -> false }

===


ok... but this is more a permanent thing. I am mostly interested in if
people want to change the meta class itself at a later point in time
instead of right from the beginning.


and I even (of course having done /ExpandoMetaClass.enableGlobally()/)
install global handlers


so your delegate is an ExpandoMC. Ok.


===

// for some triple-weird reason simply defining propertyMissing in an
extension does NOT work (never gets called)

         Object.metaClass.propertyMissing={name->

             DPA.propertyMissing(delegate,name)

         }

         Object.metaClass.static.propertyMissing={name->

             DPA.staticPropertyMissing(delegate,name)

         }

===


yeah... could be considered a bug I think.


/DPA/ is my own rather non-trivial class, whose code dynamically fixes
properties of library classes, i.e., allows me to write
/SomeLibraryClassOrInstance.foo/ for classes which have either static or
instance method /foo()/ and if so happens, /getFoo() { foo()
}/ (essentially) is installed automatically to the metaclass (the
rationale here is that the WebObjects standard, which long long predates
the unlucky Java one, has setters /setFoo(foo)/ and getters /foo()/, not
/getFoo()/).


So if we would go and say a class gets its meta class only once, but you
can control what it is if you must, then you have no problem... well
performance wise maybe

bye Jochen




Re: Small survey on the usage of the metaclass system and MOP

2024-01-08 Thread OCsite
Jochen,

> On 8. 1. 2024, at 16:10, Jochen Theodorou  wrote:
> I would like to know from users on this list mostly if they are using
> specific features of the meta class system and MOP, but especially what for.
> 
> (1) categories
> ...
> use (CategoryClass) {
>  // some code and callstack here influenced by CategoryClass
> }
> I am especially interested in knowing if you try to add a method to code that 
> is not part if the use-block here.

All the time, mostly to extend library classes, occasionally to split my own 
class implementation to more source files. I never ever use the use-block.

My aim here is to have something as close to the Objective-C categories as 
possible. Not entirely successful (the worst problem is that the Groovy 
category-based extensions do not work properly through introspection, whilst 
methods added by an ObjC category are real first-class citizens, not 
distinguishable from the “normal” ones), but I am reasonably close and the 
support is immensely useable to me.

For convenience, I did my own Extension ASTT closely based on the Alex 
Tkachman's Category, but improved a bit, so that
- inside of my @Extension(String) class MyStringExtensions { ... }, I can put 
both instance and static extension methods, and for the latter, my ASTT 
automatically creates an appropriate static extension class;
- the extension class list is collected compile-time and (eventually when my 
build script creates the application) automatically added to the 
org.codehaus.groovy.runtime.ExtensionModule manifest, so that they just-work 
without any extra ado.

> (2) per instance meta classes
> https://groovy-lang.org/metaprogramming.html#_per_instance_metaclass
> shows examples here
> Anyone using that?

Can't recall I ever needed that.

> (3) Custom meta class
> Anyway trying to force the usage of something else then MetaClassImpl
> for the meta class?

Well sort of, though a pretty trivial one. My goal is to get rid of NPEs; in my 
personal opinion that darned thing is a proper disaster and the right behaviour 
is a completely consistent null-propagation (essentially what Groovy calls a 
“safe dispatch”). Among many other things, what I do is

===
def mc=new OCSNMC(org.codehaus.groovy.runtime.NullObject)
mc.initialize()
org.codehaus.groovy.runtime.NullObject.metaClass=mc
... ...
}
class OCSNMC extends DelegatingMetaClass {
OCSNMC(Class clazz){
super(clazz)
}
Object invokeMethod(Object object, String methodName, Object[] arguments) {
if (arguments.size()==1 && methodName=='is') return arguments[0]==null
if (arguments.size()==0 && methodName=='iterator') return [].iterator()
if (arguments.size()==0 && methodName=='hasZeroValue') return YES
null
}
// alas, does not seem to work for getProperty; that one must be supported 
by ASTTs
}
===

Aside that, not sure if interesting to you, but I install my own methods into 
metaclasses all the time, like e.g.,

===
NSMutableDictionary.metaClass.putAt<<{ key,value ->
if (value==nil) delegate.removeObjectForKey(key)
else delegate.setObjectForKey(value,key)
}
...
NSKeyValueCoding.NullValue.class.metaClass.asBoolean={ -> false }
===

and I even (of course having done ExpandoMetaClass.enableGlobally()) install 
global handlers

===
// for some triple-weird reason simply defining propertyMissing in an 
extension does NOT work (never gets called)
Object.metaClass.propertyMissing={name->
DPA.propertyMissing(delegate,name)
}
Object.metaClass.static.propertyMissing={name->
DPA.staticPropertyMissing(delegate,name)
}
===

DPA is my own rather non-trivial class, whose code dynamically fixes properties 
of library classes, i.e., allows me to write SomeLibraryClassOrInstance.foo for 
classes which have either static or instance method foo() and if so happens, 
getFoo() { foo() } (essentially) is installed automatically to the metaclass 
(the rationale here is that the WebObjects standard, which long long predates 
the unlucky Java one, has setters setFoo(foo) and getters foo(), not getFoo()).

Thanks and all the best,
OC




Re: Small survey on the usage of the metaclass system and MOP

2024-01-08 Thread Christopher Smith
I myself use @POJO almost everywhere.

On Mon, Jan 8, 2024, 09:11 Jochen Theodorou  wrote:

> Hi all,
>
> I would like to know from users on this list mostly if they are using
> specific features of the meta class system and MOP, but especially what
> for.
>
>
> (1) categories
>
> https://blog.mrhaki.com/2009/09/groovy-goodness-use-categories-to-add.html
> shows an example. Basically you have
>
> use (CategoryClass) {
>// some code and callstack here influenced by CategoryClass
> }
>
> I am especially interested in knowing if you try to add a method to code
> that is not part if the use-block here.
>
>
> (2) per instance meta classes
>
> https://groovy-lang.org/metaprogramming.html#_per_instance_metaclass
> shows examples here
>
> Anyone using that?
>
> (3) Custom meta class
>
> Anyway trying to force the usage of something else then MetaClassImpl
> for the meta class? If you do not understand the question at all, then
> the answer would be no.
>
>
> bye Jochen
>


Small survey on the usage of the metaclass system and MOP

2024-01-08 Thread Jochen Theodorou

Hi all,

I would like to know from users on this list mostly if they are using
specific features of the meta class system and MOP, but especially what for.


(1) categories

https://blog.mrhaki.com/2009/09/groovy-goodness-use-categories-to-add.html
shows an example. Basically you have

use (CategoryClass) {
  // some code and callstack here influenced by CategoryClass
}

I am especially interested in knowing if you try to add a method to code
that is not part if the use-block here.


(2) per instance meta classes

https://groovy-lang.org/metaprogramming.html#_per_instance_metaclass
shows examples here

Anyone using that?

(3) Custom meta class

Anyway trying to force the usage of something else then MetaClassImpl
for the meta class? If you do not understand the question at all, then
the answer would be no.


bye Jochen


AW: Strange behaviour when using the Grab annotation

2024-01-08 Thread UIT
Hello Paul!

That explains all the - at least to me - strange behavior.

I also saw in the doc Bob pointed me to that there is a grape resolve command 
to check the transitive dependencies of a grape.

So no need to set up a dummy script for this and delete the ~/.groovy/grapes 
directory and re-fetch the jars. 

Thanks again to all involved here.

Regards

Clemens

-Ursprüngliche Nachricht-
Von: Paul King  
Gesendet: Montag, 8. Januar 2024 13:13
An: users@groovy.apache.org
Betreff: Re: Strange behaviour when using the Grab annotation

[Sie erhalten nicht häufig E-Mails von pa...@asert.com.au. Weitere 
Informationen, warum dies wichtig ist, finden Sie unter 
https://aka.ms/LearnAboutSenderIdentification ]

If you look up the Javadoc for Grab, you will see that it can be on more things 
than just an import. It can be on a type, a method, a field, a local variable 
and so forth. It can't be used on a single statement. The suggestion for 
placing it on an import statement is really just a suggestion. It is often 
preferred to place it there rather than on a field or single method because it 
will be applicable for the whole script regardless of where you place it - you 
wouldn't want someone to think the @Grab was only applicable for a particular 
method for instance.

If you just have a single println and nothing else, that is a local variable 
called "println" which will come from the binding and have value null since you 
haven't defined any value.

Cheers, Paul.


Virus-free.www.avast.com

<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>

On Sun, Jan 7, 2024 at 7:21 PM Clemens Quoss  wrote:
>
> Hello Bob!
>
> Thanks for your answer. Yes, of course the right way would be to also use the 
> 'grabbed' dependency in one way or the other.
>
> This test script of mine was for investigating what dependency in a large 
> script of mine pulls in groovy-all:2.4.x making this script unusable with 
> Groovy 4.x due to classpath clashes.
>
> Therefore i wrote this small test script putting in only one Grab at a time 
> and deleting ~/.groovy/grapes between the runs to see what is transitively 
> pulled from what @Grab.
>
> And you do not have to write it like this:
>
> @Grab(...)
> import ...
>
> @Grab(...)
> import ...
>
> Grab is not an annotation for a dedicated import statement. I think this part 
> of the doc is misleading.
>
> BTW, i forgot to mention that the script works if i leave out the "Hallo, 
> Groovy!" part and only work with an empty println.
>
> So i do still believe it is a bug of some sort.
>
> Regards
>
> Clemens
>
> Am 07.01.2024 um 01:31 schrieb Bob Brown:
>
> I think that @Grab needs to be ‘attached’ to something like an import.
>
>
>
> The doco (https://groovy-lang.org/grape.html) says:
>
>
>
> “””
>
> Note that we are using an annotated import here, which is the recommended way.
>
> “””
>
>
>
> Take a look at:
>
>
>
> https://dzone.com/articles/groovy-and-jsch-sftp
>
>
>
> HTH
>
>
>
> BOB
>
>
>
> From: Quoß, Clemens (UIT) 
> Sent: Sunday, January 7, 2024 7:04 AM
> To: users@groovy.apache.org
> Subject: Strange behaviour when using the Grab annotation
>
>
>
> Hello everyone!
>
>
>
> When I am running this script with 4.0.17 …
>
> >>>
> @GrabResolver(name = 'nexus', root = 'https://…')
>
> @Grab(group = 'com.jcraft', module = 'jsch', version = '0.1.55')
>
>
>
> println "Hallo, Groovy!"
>
> <<<
>
> … I am getting this:
>
> >>>
> org.codehaus.groovy.control.MultipleCompilationErrorsException: startup 
> failed:
>
> C:\Temp\test.groovy: 4: Unexpected input: '"Hallo, Groovy!"' @ line 4, column 
> 9.
>
>println "Hallo, Groovy!"
>
>^
>
>
>
> 1 error
>
> <<<
>
> When I remove the Grapes annotations everything works as expected.
>
>
>
> Has anyone encountered similar issues? Is there a cure? Is this considered a 
> bug? To me it looks that way. But maybe I am missing something here.
>
> TIA
>
> Regards
>
>
>
> Union IT-Services GmbH
>
> Clemens Quoß
>
> FDI-INT
>
> Senior Software Entwickler
>
> Neue Mainzer Straße 12
>
> 60311 Frankfurt am Main
>
>
>
> Tel. +49 69 2567 1241
>
> Fax +49 69 2567 61241
>
> Mobil +49 151 55157195
>
> clemens.qu...@union-investment.de
>
>
>
> Sitz der Gesellschaft: Weißfrauenstraße 7, 60311 Frankfurt am Main
>
> Registergericht: Amtsgericht Frankfurt am Main HRB 33314
>
> Geschäftsführer: Stephan Nasterlack, Siegfried Ehlert, Tobias Meier, 
> Gregor Sauerzapf
>
>


Re: Strange behaviour when using the Grab annotation

2024-01-08 Thread Paul King
If you look up the Javadoc for Grab, you will see that it can be on
more things than just an import. It can be on a type, a method, a
field, a local variable and so forth. It can't be used on a single
statement. The suggestion for placing it on an import statement is
really just a suggestion. It is often preferred to place it there
rather than on a field or single method because it will be applicable
for the whole script regardless of where you place it - you wouldn't
want someone to think the @Grab was only applicable for a particular
method for instance.

If you just have a single println and nothing else, that is a local
variable called "println" which will come from the binding and have
value null since you haven't defined any value.

Cheers, Paul.


Virus-free.www.avast.com

<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>

On Sun, Jan 7, 2024 at 7:21 PM Clemens Quoss  wrote:
>
> Hello Bob!
>
> Thanks for your answer. Yes, of course the right way would be to also use the 
> 'grabbed' dependency in one way or the other.
>
> This test script of mine was for investigating what dependency in a large 
> script of mine pulls in groovy-all:2.4.x making this script unusable with 
> Groovy 4.x due to classpath clashes.
>
> Therefore i wrote this small test script putting in only one Grab at a time 
> and deleting ~/.groovy/grapes between the runs to see what is transitively 
> pulled from what @Grab.
>
> And you do not have to write it like this:
>
> @Grab(...)
> import ...
>
> @Grab(...)
> import ...
>
> Grab is not an annotation for a dedicated import statement. I think this part 
> of the doc is misleading.
>
> BTW, i forgot to mention that the script works if i leave out the "Hallo, 
> Groovy!" part and only work with an empty println.
>
> So i do still believe it is a bug of some sort.
>
> Regards
>
> Clemens
>
> Am 07.01.2024 um 01:31 schrieb Bob Brown:
>
> I think that @Grab needs to be ‘attached’ to something like an import.
>
>
>
> The doco (https://groovy-lang.org/grape.html) says:
>
>
>
> “””
>
> Note that we are using an annotated import here, which is the recommended way.
>
> “””
>
>
>
> Take a look at:
>
>
>
> https://dzone.com/articles/groovy-and-jsch-sftp
>
>
>
> HTH
>
>
>
> BOB
>
>
>
> From: Quoß, Clemens (UIT) 
> Sent: Sunday, January 7, 2024 7:04 AM
> To: users@groovy.apache.org
> Subject: Strange behaviour when using the Grab annotation
>
>
>
> Hello everyone!
>
>
>
> When I am running this script with 4.0.17 …
>
> >>>
> @GrabResolver(name = 'nexus', root = 'https://…')
>
> @Grab(group = 'com.jcraft', module = 'jsch', version = '0.1.55')
>
>
>
> println "Hallo, Groovy!"
>
> <<<
>
> … I am getting this:
>
> >>>
> org.codehaus.groovy.control.MultipleCompilationErrorsException: startup 
> failed:
>
> C:\Temp\test.groovy: 4: Unexpected input: '"Hallo, Groovy!"' @ line 4, column 
> 9.
>
>println "Hallo, Groovy!"
>
>^
>
>
>
> 1 error
>
> <<<
>
> When I remove the Grapes annotations everything works as expected.
>
>
>
> Has anyone encountered similar issues? Is there a cure? Is this considered a 
> bug? To me it looks that way. But maybe I am missing something here.
>
> TIA
>
> Regards
>
>
>
> Union IT-Services GmbH
>
> Clemens Quoß
>
> FDI-INT
>
> Senior Software Entwickler
>
> Neue Mainzer Straße 12
>
> 60311 Frankfurt am Main
>
>
>
> Tel. +49 69 2567 1241
>
> Fax +49 69 2567 61241
>
> Mobil +49 151 55157195
>
> clemens.qu...@union-investment.de
>
>
>
> Sitz der Gesellschaft: Weißfrauenstraße 7, 60311 Frankfurt am Main
>
> Registergericht: Amtsgericht Frankfurt am Main HRB 33314
>
> Geschäftsführer: Stephan Nasterlack, Siegfried Ehlert, Tobias Meier, Gregor 
> Sauerzapf
>
>