You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@groovy.apache.org by Jochen Theodorou <bl...@gmx.org> on 2026/08/31 16:39:20 UTC

GEP-31

Hi,

I just progressed on some work that was dangling for a really long time 
and results are now in GEP-31

https://github.com/apache/groovy-website/blob/asf-site/site/src/site/wiki/GEP-31.adoc

This is not an implementation spec, it is not on purpose. It should be 
enough to start an implementation and to discuss the general idea. I 
think it has a lot of value. This is not really a new MOP or for 
performance, this is more a story about protected a runtime or library 
from unwanted changes in the meta class universe. One of my long term 
goals is still a Groovy implemented 100% in Groovy... at least to make 
it possible. Even static compilation in its current state will not make 
this possible as extension methods may brake out into unrestricted 
scopes. Imagine implementing MetaClassImpl in Groovy and then a DGM 
wants to use the metaclass of MetaClassImpl for method dispatch. And now 
think this extension method is used to get the target method. GEP-31 can 
solve that problem.

```Groovy
@Realm(LIB_X_REALM)
@CompileStatic
class LibX {
     ...
}
```

with
`LIB_X_REALM = Core extensions + LibX extensions + isolated MetaClass 
semantics`

then LibX does not suffer extension method pollution from another LibY 
it depends on and just happens to be on the classpath. The static 
compiler has a precise set of extension methods to consider, instead of 
discovering them through the service approach we have right now, which 
is generally open and depends on what I currently have on my compile 
classpath. Since the extension methods are known at compile time now, 
without a service lookup, the extension methods do not need to be 
precompiled or discovered.

```Groovy
class Person {
     String name
}

@RealmDef
LIBRARY_REALM = {
     extends GROOVY_DYN
     metaclass isolated
}

@Realm(LIBRARY_REALM)
class Library {
     static void install() {
         Person.metaClass.greeting = { "hello $name" }
     }

     static String run(Person person) {
         person.greeting()
     }
}

def person = new Person(name: 'Joe')

assert !person.metaClass.respondsTo(person, 'greeting')

use(LIBRARY_REALM) {
     Library.install()
     assert person.greeting() == 'hello Joe'
}

assert !person.metaClass.respondsTo(person, 'greeting')
```

Could be an interesting story for using meta programming in testing.

I also think this is groundwork for allowing a future new MOP and 
especially experimental MOPs in a controlled way, without having to 
exhibit it to the user. The realm specifies the MOP. It could be used to 
enable a completely different MOP.

I would be interested in thoughts about this.

bye Jochen

Re: GEP-31

Posted by Jochen Theodorou <bl...@gmx.org>.
Hi Matt,

more inline

On 9/2/26 17:14, Matt M wrote:
> Hello,
> 
> 
> I read through the proposal and it sounds interesting. My initial 
> impression is that it might not have a lot relevance to end users (maybe 
> it does for specific library writers or as a kind of "constraint" around 
> certain code? (I hesitate to say anything else or in other ways here in 
> so far as to draw incorrect or unintended correlations)). In its current 
> iteration, it seems focused on being a compiler level enhancement/ 
> requirement for future refactoring and redesigns than a necessarily 
> highly applicable, broadly relevant user facing feature. None of which 
> is bad.

yeah, I guess I was emphasizing the compiler part too much.

Some problems this tries to solve:

**Extension methods**

* In the static compiler, extension methods from a library dependency 
can influence your code, even if you use nothing from that library.
* Extension methods are not available for internal use only. A library 
cannot provide extension methods for its own implementation without also 
making them available to users.
* Extension methods may have to be written in Java to avoid interference 
from the MetaClass system.
* Users cannot define their own extension methods in the same way as 
library-provided extension methods.

**Categories**

Categories are the user-level variant of extension methods, but their 
scope is problematic because it is thread-bound.

* Most categories are actually intended to apply to a call site, which 
is why this GEP discusses lexical categories.
* Dynamic categories complicate the implementation and affect every call 
site that Groovy resolves dynamically. Being able to turn them off 
permits a simpler and more reliable dispatch implementation, which also 
benefits tooling and other implementations of the call site.

**Groovy core and Groovy modules**

* Some parts of Groovy core, such as extension methods and the MetaClass 
implementation, cannot be written in Groovy itself without depending on 
the dynamic mechanisms they implement. This is not a proposal to rewrite 
Groovy in Groovy tomorrow, but currently there are places where this is 
not possible at all.
* The old MetaClass system has accumulated several generations of 
implementation techniques: reflection, generated call sites, primitive 
optimizations, invokedynamic, and others. It needs a redesign that is 
largely blocked by the requirement to preserve the legacy API.

**Optimized dynamic compilation**

This is already discussed extensively in the GEP. The basic idea is 
dynamic Groovy with compile-time optimizations controlled by which types 
and dynamic features are available.

For the user in short, more control, more tooling support under some 
specific conditions, a new construct for categories.

> I believe I got the gist of the idea that the GEP is getting at. It 
> would probably be really useful to call out and accentuate the exact 
> purpose and mission statement of the problem(s) that it seeks to solve 
> (e.g. "Start to work towards enabling strong encapsulation and isolation 
> of dynamic capabilities in a controlled and deterministic way in so far 
> as to prevent unintended leaks of the MOP and MOP-like functionality 
> outside of an articulated scope.”).

the mission statement I would probably phrase along this:

The goal of realms is to make Groovy's dynamic semantics explicit and 
controllable. A realm defines which dynamic capabilities are visible to 
a piece of code, allowing extension methods, categories, the MetaClass 
system, and other dynamic behavior to be selected, isolated, and 
optimized independently of the surrounding application.

"which dynamic capabilities are visible to a piece of code" does not 
mean encapsulation in the Java sense. This is not an OOP concept. 
Optimization is a byproduct of having more control - control a human and 
the compiler can understand.

Can a user continue writing his programs as before, most likely. The 
intention is not to break existing code with this. I have to see if that 
is actually realizable, but I think it should. And if there are changes, 
then in the meta class api maybe.

> At a linguistics level for the idea, I think the term |Realm| is not 
> quite a good fit for describing the concept. It's quite whimsical and 
> stylized without quickly and clearly explaining/alluding to what pattern 
> of functionality it represents or does, even colloquially. I would 
> suggest changing it to some version or combination of the various 
> explanatory terms/word-phrases already used in the GEP to explain/ 
> describe the idea itself such as |Environment|, |Scope|, | 
> EnvironmentScope|, |ImmutableContext|, etc. just to name a few. For 
> example, an initial idea of a clearer design that came to mind was that 
> a |@Realm| (i.e. in usage form) is better described as a |@Scope| and a 
> |@RealmDefinition| is described as an |@Environment|. Therefore, one way 
> a user could think of it is as "You define an @Environment and then use 
> that environment in/as a @Scope for code to execute in/under". Makes the 
> mental model clearer and more explicit.

Names can still be changed, the concept is what needs acceptance first. 
To give you an example of my impressions... When I hear scope, I think 
block scope, variable scope and so on. Environment I think of a system, 
environment scope I have no idea. If I had to do more with Kubernetes I 
would probably associate realm with that world. Just see the names as 
"work in progress".

> On a minor hiccup I had in my readings is the word "properties” being 
> used. I initially got a little confused at how it was saying that these 
> concepts would interact with and work with Properties (i.e. Groovy's | 
> getters/setters|) since it said: "A realm inherits the definition of one 
> other realm and may replace individual properties.”. I incorrectly 
> conflated the term with the Groovy literal idea of |Properties| which is 
> not what was intended. It might be better and clearer to say that what 
> the GEP is referring to are environmental context attributes or 
> something else of that kind.

For now I will then just use attributes, which really only works better 
against Groovy and Java developers, because attributes is not used so 
much there to describe fields.

> At a semantic level, overall, the GEP is going a bit deeper than the 
> idea that might be canonically known as namespaces. It's closer to 
> implementing specific resolution handling and isolation rules/semantics 
> for strong encapsulation of/for the MOP. I tried to draw a corollary to 
> other languages that implement the same concept or at least notionally 
> seem to go for the same idea. The best one that that I could arrive at 
> was idea of "function environments" in Lua. GEP-31 seems similar in 
> vision albeit highly constrained on the MOP and extension methods 
> exclusively in the current iteration.

Dart, Kotlin and Scala provide statically scoped extension mechanisms, 
Ruby refinements are closer to lexical categories. JavaScript realms 
instead isolate global execution environments. These mechanisms address 
parts of the problem that realms address, but none combines them with 
explicit control over Groovy's MetaClass-based dispatch.

Frankly the whole problem is home made and rooted in the complex MOP

[...]
>   * How does backwards compatibility work in so far as the compiler’s
>     public API/ABI is concerned? At first glance, it seems completely
>     transparent and seamless. However, I wouldn't want it to be what
>     project jigsaw was to Java (i.e. probably the least understood, most
>     hated/disliked feature ever implemented in Java; that was largely
>     seen as solely for the benefit of the compiler/language devs at the
>     expense of everyone else). [I know that I am probably editorializing
>     a fair bit here but based on my experience and interactions with all
>     kinds of other developers in the Java space and even what the JVM
>     architects said themselves, it's not really a disingenuous or even
>     an unfair perspective].

well... good that you did not see some of the mails I exchanged with 
those guys back then. That is all I will say about me not liking jigsaw, 
or I will rant for a while.

I don´t think the ABI will change for this. I do not see where and what 
for. There will be a new bootstrap method, to take the realm as 
parameter, but the old one will continue to work and assume GROOVY_DYN 
realm, which is 100% compatible to today.

>   * What are rules for inheritance as it relates to a Realm and all of
>     its layers' priority and ordering? How does a Realm inherit from
>     another Realm and how do we envision that working (not from a syntax
>     perspective but rather like how do we envision that actually working
>     under the hood)? What is the mental model for its inheritance that
>     is made clear for end users (folks in general struggle to understand
>     OOP inheritance as it is already)? There's a lot of talk about
>     layers and there seem to be quite many and they have various planned
>     intricacies for how they each interact with each other and those
>     above/below each other, in regards to precedence and priority.

Realms do not strictly inherit in the OO sense. A realm definition 
declares capabilities. Extending another realm means taking those 
capabilities and then overwriting selected ones with your own 
definition. The resulting realm is an ordered composition of layers.

The usage side determines where the definition is applied. The usages in 
the proposal are use(MyRealm) { ... } and @Realm(MyRealm). MyRealm is 
more or less a token given to the runtime.

At runtime, that token is associated with an ordered list of layers per 
class. The exact shape is not defined yet and will depend on the 
implementation, but most likely there will be one layer per extension 
method class, one for the small MOP, one for the extended MOP, and one 
for mutable MetaClasses.

To dispatch a method, the runtime goes through the layers in order. Each 
layer determines which targets are applicable; the applicable targets 
may be empty. The most specific applicable method is selected as the 
dispatch target. If no layer provides an applicable target, the dispatch 
results in MissingMethodException.

Think of each layer as a specialist. We already have most of this 
machinery in current Groovy, both as code and partially as a model - we 
call it a meta class. The proposal separates the code paths and models 
the dispatch environment more explicitly. Once it is represented as a 
model, we can reason about it; with the current implementation, much of 
that reasoning is implicit in the code. That combination of model and 
code is currently spread between the meta classes and ClassInfo, as well 
as several more classes.

>   * How does access for Realms work? Are they public by default and/or
>     can they be designated as private, package-private, etc.? Would
>     protected be allowed?

I did not explicitly define that yet, yes. But since a definition will 
be represented as class, it goes with the visibility of the class. And I 
guess I should move the declaration style I used before to an explicit 
class, where you can apply a modifier as well. Then simply normal class 
rules apply.

>   * What is the compelling use case/reason for a user to want to even
>     use/know about/understand this feature at all? I would want to avoid
>     it having the same kind of confusion and/or kind of general disdain/
>     disinterest at understanding as there is/was around the JVM's
>     concepts of classpath and modulepath interplay.

More control over the dynamic semantics of a piece of code.

A library can choose which extension methods, categories and MetaClass 
behavior its code uses, without implicitly depending on whatever dynamic 
environment happens to surround it. An application can do the same when 
it wants a particular dynamic behavior or wants to isolate parts of the 
application from each other.

Jigsaw mainly restricts what code can access. Realms do not primarily 
restrict access. They let the programmer choose which dynamic 
capabilities are present. There is isolation, yes, but there is no 
*privileged* "inside" that needs to be protected from an "outside".

Think:
My library should behave the same way whether or not the application 
happens to have some unrelated extension method or MetaClass 
customization installed.

>   * Are Realms repeatable/stackable (e.g. |@Realm(X) @Realm(Y) def
>     my_method() { ... }|)? I could see it going either way on allowing
>     or disallowing this. If allowed, there's then the challenge of
>     checking for overlaps/conflicting extensions, precedence handling,
>     and cycle detection that would have to be done at each usage site.
>     If not allowed, then there's the challenge of how to allow users to
>     compose Realms and/or extending Realms either that they didn't write
>     and/or don't have access to.

|@Realm(X) @Realm(Y) def my_method() { ... }| is one usage site only. 
But no, I would not allow that.

> At a syntax level, I know this will come off really blunt and harsh, I 
> apologize in advance. I /really/ don't like the shape or design of the 
> syntax for implementing a Realm's definition at all, as it is stated in 
> the GEP. It looks very out-of-place and like non-idiomatic Groovy. It 
> reads /very/ strangely and is awkward to understand at a glance since it 
> seems like a hybrid of a not-closure closure and half a class 
> declaration with a weird set assignment/definition thrown in for good 
> measure. Syntactically, it's just very confusing to read/understand and 
> I would imagine it will be quite kludge'y to implement at a grammar/ 
> syntax level as is. Again, I don't mean to draw the same parallel to 
> jigsaw but it comes off as feeling like module-info.java all over again. 
> Again, apologies for being really blunt and just hating on it.

you will be then surprised to hear that this requires not changes to the 
syntax at all. Instead it is a DSL, a local transform changes the 
semantics. I would probably now move the block into the annotation and 
annotate a class that defines modifier and name. But I doubt that 
changes your verdict. I am open for a better version of course. Only 
that I do not want this definition to be a runtime construct. The result 
should be readable without initializing the class it is based on.

> I think it would be simpler, clearer, and more consistent to not get 
> clever at all with the syntax here and just be super boring about it by 
> having it be implemented it as a typical plain-old Groovy class like 
> anything else. Using common semantics like a constructor and a super 
> class to clearly define the API contract of it all. The compiler could 
> just scan for any and all classes that extend the super class (or 
> implement a particular interface as that could be another route to go) 
> and process those first/separately as environments/realm definitions. 
> Sometimes simple and boring is best.

The class-scanning part is exactly what I do not want. A realm should be 
an explicit semantic dependency, not something the compiler discovers by 
scanning the classpath. Otherwise adding an unrelated realm to the 
classpath can change compilation semantics, and incremental compilation 
becomes harder to reason about.

I also do not want a realm definition to require class initialization or 
object construction. The definition is metadata. I want the compiler and 
runtime to be able to inspect it directly from the class file, using 
reflection or ASM, and obtain the realm token without executing user code.

So a plain class can still be the underlying representation, but the 
realm definition itself needs to be declarative and explicitly 
referenced rather than discovered by scanning for subclasses.

The class is the discovery mechanism.

> At a conceptual level, I like the idea of what the GEP is shooting for 
> in the broad strokes. There's some details to flesh out and refine. I 
> think it would be really helpful as well to see a few illustrative 
> examples and samples of the idea in motion so that someone could get a 
> sense of what it enables, how it would work, and the value it adds for 
> them and just getting a bird's eye view of it all.


**Library isolation**

```groovy
MY_LIB = {
     extends GROOVY_DYN
     extensions MyExtensions
     metaclass isolated
}
```

and use `@Realm(MY_LIB)` for its implementation. The library then does 
not accidentally acquire extension methods or MetaClass changes from the 
application using it.

**Explicit extension dependencies**

Instead of discovering extension methods from everything on the 
classpath, a realm explicitly declares them:

```groovy
MY_LIB = {
     extensions [MyExtensions, SOME_OTHER_REALM.extensions]
}
```

**Lexical categories**

A category can be represented as a derived realm for a lexical region:

```groovy
use(MyCategory) {
     // category semantics apply here
}
```

rather than changing thread-bound dynamic state. This is closer to how 
categories are usually intended to be used, and it also gives the 
compiler a known semantic environment for those call sites.

**Groovy itself**

The same mechanism allows different parts of Groovy to choose different 
dispatch environments. For example, a new MetaClass implementation could 
be used in a realm without requiring all of Groovy to use it 
immediately. This is also the direction in which I see the realm concept 
helping with a more optimized form of dynamic compilation.

Complete example would probably be too much for this mail.

> On a meta note, what Groovy version is this tentatively planned to 
> target? I didn't see any mention of a target version but I would 
> speculate v8 or v9 and beyond.

well... maybe Groovy 7 is too short. But nothing says that it has to be 
complete in version 7.
> On a meta meta note, the original email came through just fine on my end 
> and I even saw it on the mailing list archive too. Not sure that helps 
> at all or anything but just throwing that out there. Emails/servers 
> being wonky is one of the many fun caveats of old school mailing list 
> style development.

I opened https://issues.apache.org/jira/browse/INFRA-28349 for this, and 
we are both victims of this.

> I hope this is helpful. Thank you for writing this GEP up regardless.

The worst would have been nobody caring to even answer - so thank you 
for caring! I think no good idea can be good enough if it cannot 
withstand some skepticism.

bye Jochen

Re: GEP-31

Posted by Matt M <ma...@proton.me>.
Hello,

I read through the proposal and it sounds interesting. My initial
impression is that it might not have a lot relevance to end users
(maybe it does for specific library writers or as a kind of
"constraint" around certain code? (I hesitate to say anything else or
in other ways here in so far as to draw incorrect or unintended
correlations)). In its current iteration, it seems focused on being a
compiler level enhancement/requirement for future refactoring and
redesigns than a necessarily highly applicable, broadly relevant
user facing feature. None of which is bad.

I believe I got the gist of the idea that the GEP is getting at. It
would probably be really useful to call out and accentuate the exact
purpose and mission statement of the problem(s) that it seeks to solve
(e.g. "Start to work towards enabling strong encapsulation and
isolation of dynamic capabilities in a controlled and deterministic
way in so far as to prevent unintended leaks of the MOP and MOP-like
functionality outside of an articulated scope.”).

At a linguistics level for the idea, I think the term `Realm` is not
quite a good fit for describing the concept. It's quite whimsical and
stylized without quickly and clearly explaining/alluding to what
pattern of functionality it represents or does, even colloquially. I
would suggest changing it to some version or combination of the
various explanatory terms/word-phrases already used in the GEP to
explain/describe the idea itself such as `Environment`, `Scope`,
`EnvironmentScope`, `ImmutableContext`, etc. just to name a few. For
example, an initial idea of a clearer design that came to mind was
that a `@Realm` (i.e. in usage form) is better described as a `@Scope`
and a `@RealmDefinition` is described as an `@Environment`. Therefore,
one way a user could think of it is as "You define an @Environment and
then use that environment in/as a @Scope for code to execute
in/under". Makes the mental model clearer and more explicit.

On a minor hiccup I had in my readings is the word "properties” being
used. I initially got a little confused at how it was saying that
these concepts would interact with and work with Properties (i.e.
Groovy's `getters/setters`) since it said: "A realm inherits the
definition of one other realm and may replace individual properties.”.
I incorrectly conflated the term with the Groovy literal idea of
`Properties` which is not what was intended. It might be better and
clearer to say that what the GEP is referring to are environmental
context attributes or something else of that kind.

At a semantic level, overall, the GEP is going a bit deeper than the
idea that might be canonically known as namespaces. It's closer to
implementing specific resolution handling and isolation
rules/semantics for strong encapsulation of/for the MOP. I tried to
draw a corollary to other languages that implement the same concept or
at least notionally seem to go for the same idea. The best one that
that I could arrive at was idea of "function environments" in Lua.
GEP-31 seems similar in vision albeit highly constrained on the MOP
and extension methods exclusively in the current iteration.

In other words, as mentioned before, the idea is to start to work
towards a form of strong encapsulation and strong isolation for
Groovy's dynamic capabilities, specifically around extension methods
and the MOP. Some of the initial questions I had were:

- How does backwards compatibility work in so far as the compiler’s
   public API/ABI is concerned? At first glance, it seems completely
   transparent and seamless. However, I wouldn't want it to be what
   project jigsaw was to Java (i.e. probably the least understood, most
   hated/disliked feature ever implemented in Java; that was largely
   seen as solely for the benefit of the compiler/language devs at the
   expense of everyone else). [I know that I am probably editorializing
   a fair bit here but based on my experience and interactions with all
   kinds of other developers in the Java space and even what the JVM
   architects said themselves, it's not really a disingenuous or even an
   unfair perspective].
- What are rules for inheritance as it relates to a Realm and all of
   its layers' priority and ordering? How does a Realm inherit from
   another Realm and how do we envision that working (not from a syntax
   perspective but rather like how do we envision that actually working
   under the hood)? What is the mental model for its inheritance that
   is made clear for end users (folks in general struggle to understand
   OOP inheritance as it is already)? There's a lot of talk about
   layers and there seem to be quite many and they have various planned
   intricacies for how they each interact with each other and those
   above/below each other, in regards to precedence and priority.
- How does access for Realms work? Are they public by default and/or
   can they be designated as private, package-private, etc.? Would
   protected be allowed?
- What is the compelling use case/reason for a user to want to even
   use/know about/understand this feature at all? I would want to avoid
   it having the same kind of confusion and/or kind of general
   disdain/disinterest at understanding as there is/was around the
   JVM's concepts of classpath and modulepath interplay.
- Are Realms repeatable/stackable (e.g.
   `@Realm(X) @Realm(Y) def my_method() { ... }`)? I could see it going
   either way on allowing or disallowing this. If allowed, there's then
   the challenge of checking for overlaps/conflicting extensions,
   precedence handling, and cycle detection that would have to be done
   at each usage site. If not allowed, then there's the challenge of how
   to allow users to compose Realms and/or extending Realms either
   that they didn't write and/or don't have access to.

At a syntax level, I know this will come off really blunt and harsh, I
apologize in advance. I _really_ don't like the shape or design of the
syntax for implementing a Realm's definition at all, as it is stated
in the GEP. It looks very out-of-place and like non-idiomatic Groovy.
It reads _very_ strangely and is awkward to understand at a glance
since it seems like a hybrid of a not-closure closure and half a class
declaration with a weird set assignment/definition thrown in for good
measure. Syntactically, it's just very confusing to read/understand
and I would imagine it will be quite kludge'y to implement at a
grammar/syntax level as is. Again, I don't mean to draw the same
parallel to jigsaw but it comes off as feeling like module-info.java
all over again. Again, apologies for being really blunt and just
hating on it.

I think it would be simpler, clearer, and more consistent to not get
clever at all with the syntax here and just be super boring about it
by having it be implemented it as a typical plain-old Groovy class
like anything else. Using common semantics like a constructor and a
super class to clearly define the API contract of it all. The compiler
could just scan for any and all classes that extend the super class
(or implement a particular interface as that could be another route to
go) and process those first/separately as environments/realm
definitions. Sometimes simple and boring is best.

At a conceptual level, I like the idea of what the GEP is shooting
for in the broad strokes. There's some details to flesh out and
refine. I think it would be really helpful as well to see a few
illustrative examples and samples of the idea in motion so that
someone could get a sense of what it enables, how it would work, and
the value it adds for them and just getting a bird's eye view of it
all.

On a meta note, what Groovy version is this tentatively planned to
target? I didn't see any mention of a target version but I would
speculate v8 or v9 and beyond.

On a meta meta note, the original email came through just fine on my
end and I even saw it on the mailing list archive too. Not sure that
helps at all or anything but just throwing that out there.
Emails/servers being wonky is one of the many fun caveats of old
school mailing list style development.

I hope this is helpful. Thank you for writing this GEP up regardless.

Thanks,
Matt


------ Original Message ------
From "Jochen Theodour" <bl...@apache.org>
To dev@groovy.apache.org
Date 8/31/2026 4:45:47 PM
Subject Re: GEP-31

>
>
>Hi,
>
>
>
>forgot to send it from the apache.org account, because my normal account
>
>is not surviving the mailing list transformation properly and then gets
>
>marked as spam. That extends also to for example proton.me mails.
>
>
>
>Anyway, the original mail:
>
>On 8/31/26 18:39, Jochen Theodorou wrote:
>>
>>  Hi,
>>
>>
>>
>>  I just progressed on some work that was dangling for a really long time
>>
>>  and results are now in GEP-31
>>
>>
>>
>>  https://github.com/apache/groovy-website/blob/asf-site/site/src/site/
>>
>>  wiki/GEP-31.adoc
>>
>>
>>
>>  This is not an implementation spec, it is not on purpose. It should be
>>
>>  enough to start an implementation and to discuss the general idea. I
>>
>>  think it has a lot of value. This is not really a new MOP or for
>>
>>  performance, this is more a story about protected a runtime or library
>>
>>  from unwanted changes in the meta class universe. One of my long term
>>
>>  goals is still a Groovy implemented 100% in Groovy... at least to make
>>
>>  it possible. Even static compilation in its current state will not make
>>
>>  this possible as extension methods may brake out into unrestricted
>>
>>  scopes. Imagine implementing MetaClassImpl in Groovy and then a DGM
>>
>>  wants to use the metaclass of MetaClassImpl for method dispatch. And now
>>
>>  think this extension method is used to get the target method. GEP-31 can
>>
>>  solve that problem.
>>
>>
>>
>>  ```Groovy
>>
>>  @Realm(LIB_X_REALM)
>>
>>  @CompileStatic
>>
>>  class LibX {
>>
>>       ...
>>
>>  }
>>
>>  ```
>>
>>
>>
>>  with
>>
>>  `LIB_X_REALM = Core extensions + LibX extensions + isolated MetaClass
>>
>>  semantics`
>>
>>
>>
>>  then LibX does not suffer extension method pollution from another LibY
>>
>>  it depends on and just happens to be on the classpath. The static
>>
>>  compiler has a precise set of extension methods to consider, instead of
>>
>>  discovering them through the service approach we have right now, which
>>
>>  is generally open and depends on what I currently have on my compile
>>
>>  classpath. Since the extension methods are known at compile time now,
>>
>>  without a service lookup, the extension methods do not need to be
>>
>>  precompiled or discovered.
>>
>>
>>
>>  ```Groovy
>>
>>  class Person {
>>
>>       String name
>>
>>  }
>>
>>
>>
>>  @RealmDef
>>
>>  LIBRARY_REALM = {
>>
>>       extends GROOVY_DYN
>>
>>       metaclass isolated
>>
>>  }
>>
>>
>>
>>  @Realm(LIBRARY_REALM)
>>
>>  class Library {
>>
>>       static void install() {
>>
>>           Person.metaClass.greeting = { "hello $name" }
>>
>>       }
>>
>>
>>
>>       static String run(Person person) {
>>
>>           person.greeting()
>>
>>       }
>>
>>  }
>>
>>
>>
>>  def person = new Person(name: 'Joe')
>>
>>
>>
>>  assert !person.metaClass.respondsTo(person, 'greeting')
>>
>>
>>
>>  use(LIBRARY_REALM) {
>>
>>       Library.install()
>>
>>       assert person.greeting() == 'hello Joe'
>>
>>  }
>>
>>
>>
>>  assert !person.metaClass.respondsTo(person, 'greeting')
>>
>>  ```
>>
>>
>>
>>  Could be an interesting story for using meta programming in testing.
>>
>>
>>
>>  I also think this is groundwork for allowing a future new MOP and
>>
>>  especially experimental MOPs in a controlled way, without having to
>>
>>  exhibit it to the user. The realm specifies the MOP. It could be used to
>>
>>  enable a completely different MOP.
>>
>>
>>
>>  I would be interested in thoughts about this.
>>
>>
>>
>>  bye Jochen
>
>


Re: GEP-31

Posted by Jochen Theodour <bl...@apache.org>.
Hi,

forgot to send it from the apache.org account, because my normal account 
is not surviving the mailing list transformation properly and then gets 
marked as spam. That extends also to for example proton.me mails.

Anyway, the original mail:
On 8/31/26 18:39, Jochen Theodorou wrote:
> Hi,
> 
> I just progressed on some work that was dangling for a really long time 
> and results are now in GEP-31
> 
> https://github.com/apache/groovy-website/blob/asf-site/site/src/site/ 
> wiki/GEP-31.adoc
> 
> This is not an implementation spec, it is not on purpose. It should be 
> enough to start an implementation and to discuss the general idea. I 
> think it has a lot of value. This is not really a new MOP or for 
> performance, this is more a story about protected a runtime or library 
> from unwanted changes in the meta class universe. One of my long term 
> goals is still a Groovy implemented 100% in Groovy... at least to make 
> it possible. Even static compilation in its current state will not make 
> this possible as extension methods may brake out into unrestricted 
> scopes. Imagine implementing MetaClassImpl in Groovy and then a DGM 
> wants to use the metaclass of MetaClassImpl for method dispatch. And now 
> think this extension method is used to get the target method. GEP-31 can 
> solve that problem.
> 
> ```Groovy
> @Realm(LIB_X_REALM)
> @CompileStatic
> class LibX {
>      ...
> }
> ```
> 
> with
> `LIB_X_REALM = Core extensions + LibX extensions + isolated MetaClass 
> semantics`
> 
> then LibX does not suffer extension method pollution from another LibY 
> it depends on and just happens to be on the classpath. The static 
> compiler has a precise set of extension methods to consider, instead of 
> discovering them through the service approach we have right now, which 
> is generally open and depends on what I currently have on my compile 
> classpath. Since the extension methods are known at compile time now, 
> without a service lookup, the extension methods do not need to be 
> precompiled or discovered.
> 
> ```Groovy
> class Person {
>      String name
> }
> 
> @RealmDef
> LIBRARY_REALM = {
>      extends GROOVY_DYN
>      metaclass isolated
> }
> 
> @Realm(LIBRARY_REALM)
> class Library {
>      static void install() {
>          Person.metaClass.greeting = { "hello $name" }
>      }
> 
>      static String run(Person person) {
>          person.greeting()
>      }
> }
> 
> def person = new Person(name: 'Joe')
> 
> assert !person.metaClass.respondsTo(person, 'greeting')
> 
> use(LIBRARY_REALM) {
>      Library.install()
>      assert person.greeting() == 'hello Joe'
> }
> 
> assert !person.metaClass.respondsTo(person, 'greeting')
> ```
> 
> Could be an interesting story for using meta programming in testing.
> 
> I also think this is groundwork for allowing a future new MOP and 
> especially experimental MOPs in a controlled way, without having to 
> exhibit it to the user. The realm specifies the MOP. It could be used to 
> enable a completely different MOP.
> 
> I would be interested in thoughts about this.
> 
> bye Jochen