The exercise is an interesting one: how to add support for something like 
`List.of(...)` for Java 8-21 when the method exists only for 9+ and some 
behavior you seek in only in 16+.

However, is it worthwhile in this case to add new `ScriptBytecodeAdapter` 
methods to support this for records instead of just writing the bytecode you 
need based on the compile-time target bytecode version?


From: Oscar N <paintninjaproje...@outlook.com>
Sent: Monday, January 22, 2024 10:46 AM
To: dev@groovy.apache.org
Subject: [EXT] Re: Questions regarding implementation approach for GROOVY-11294

External Email: Use caution with links and attachments.

Wrapping in Collections.unmodifiableList is an option, although using List.of() 
when possible should yield better performance as it has stronger immutability 
guarantees at the JVM level (uses @jdk.internal.vm.annotation.Stable on its 
internal backing fields).

You are right that it doesn't link to internal state - I forgot that it 
performs defensive copying/makes a new list each time. You could make the 
argument that it allows mutating the returned Map to change the returned 
values, although you could also say the same for mutable record components so 
it's kind of a moot point. I suppose the main benefit is performance-wise 
again, as the immutable List/Map could be cached.
________________________________
From: Milles, Eric (TR Technology) via dev 
<dev@groovy.apache.org<mailto:dev@groovy.apache.org>>
Sent: 22 January 2024 16:04
To: dev@groovy.apache.org<mailto:dev@groovy.apache.org> 
<dev@groovy.apache.org<mailto:dev@groovy.apache.org>>
Subject: RE: Questions regarding implementation approach for GROOVY-11294


Can you just wrap what is presently returned with a call to 
Collections.unmodifiableList or Collections.unmodifiableMap?



If the return values of toList() or toMap() from a record do not link to any 
internal state, what is the concern if they are mutable or not?





From: Oscar N 
<paintninjaproje...@outlook.com<mailto:paintninjaproje...@outlook.com>>
Sent: Monday, January 22, 2024 8:53 AM
To: dev@groovy.apache.org<mailto:dev@groovy.apache.org>
Subject: [EXT] Questions regarding implementation approach for GROOVY-11294



External Email: Use caution with links and attachments.



Hello all,



While working on GROOVY-11294, I was investigating approaches for creating an 
immutable list from an array and have some questions...



Java's List.of() usually doesn't allow nulls but can on 16+ by using 
Stream.toList(). I've used the VMPlugin system to handle this with appropriate 
fallbacks depending on what's available for a given Java version.



Next I created methods in ScriptBytecodeAdapter and InvokerHelper that call it.



First question:

Should I add a createImmutableList() method to both ScriptBytecodeAdapter and 
InvokerHelper, or does it only need to be in one of those? Presumably 
createList() is in both for compatibility reasons, although I'm unsure how it 
should work for new methods.



Second question:

Would it be better to add new typed methods to ArrayGroovyMethods called 
toImmutableList() and calling that from inside the record's generated toList() 
method instead?



Third question:

If going down the ScriptBytecodeAdapter/InvokerHelper route, how deep should 
support for generating immutable lists be in the compiler?



The idea of an ImmutableListExpression or a setImmutable() method on 
ListExpression or similar for marking lists as immutable at compile-time could 
be useful in cases such as @Immutable and provide an easy way for AST 
transformers and type checkers to check and change the mutability of 
collections...



It would also theoretically allow for skipping some runtime overhead in 
situations where we know all elements are never null.



Looking forward to hearing your thoughts on this.



-Oscar


Reply via email to