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" <[email protected]>
To [email protected]
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
>
>

Reply via email to