Deconstructor reflection Was: Re: Deconstruction patterns
Brian Goetz
brian.goetz at oracle.com
Wed Mar 8 17:18:40 UTC 2023
That's sort of where I was coming from. For example, when we added
Class::getRecordComponents (which, btw, should really be a pattern), it
returns RecordComponent[] instead of List<RecordComponent>, because
that's how reflection rolls. The benefit of using List (which are
clearly "better" than arrays) is lost by the inconsistency of "some
methods return arrays, some return lists."
On 3/8/2023 12:05 PM, Dan Heidinga wrote:
> Thanks for the response. This seems reasonable though I still have an
> aversion to the Object[] return type for the `match` method though it
> fits with the way reflection works today. I hate wasting the Carrier
> runtime's benefits by immediately boxing and collecting to the array
> for reflection but maybe anything else is trying to fix the sins of
> the past?
>
> --Dan
>
> On Tue, Mar 7, 2023 at 3:16 PM Brian Goetz <brian.goetz at oracle.com> wrote:
>
>
>
> On 3/7/2023 2:51 PM, Dan Heidinga wrote:
>>
>>
>> #### Reflection
>>
>> Since matchers are a new kind of class member, they will need
>> a new kind of
>> reflective object, and a method that is analogous to
>> `Class::getConstructors`.
>> The reflective object should extend `Executable`, as all of
>> the existing
>> methods
>> on `Executable` make sense for patterns (using `Object` as
>> the return
>> type.) If
>> the pattern is reflectively invoked, it returns `null` for no
>> match, or an
>> `Object[]` which is the boxing of the values in the carrier.
>>
>>
>> This surprised me slightly and I'm not sure I follow the
>> reasoning on why the return value would be boxed and collected
>> into an Object[]?
>>
>> The design says matcher methods return Object as an opaque
>> descriptor for the actual implementation carrier object. Yet,
>> reflection will take that carrier object, and replace it with an
>> equivalent Object[] resulting in more allocations and
>> (potentially) boxing on the return path.
>>
>> I get it's a developer friendly approach but I wonder if it
>> encourages the wrong mental model about what matchers return?
>>
>> Would it make sense to add an extra step in that process so the
>> java.lang.reflect.Matcher instance has a `Object[]
>> resultToArray(Object)` method? It's more ceremony (yuck) but
>> allows avoiding the array creation and maybe the boxing on the
>> return path for allocation-sensitive callers?
>
> There's a few things here, let's try to unpack them.
>
> I agree that the actual classfile descriptor of the synthetic
> method need not be all that related to what reflection does,
> though it is nice to minimize that difference if we can.
>
> Reflection routinely boxes everything; if you're working
> reflectively, this is just the price of entry? MethodHandles are a
> different story, of course, and we should be able to unreflect a
> Matcher to something that can be invoked directly.
>
> I had been assuming that `invoke` was a method on Executable, but
> now that I look, I realize that invocation lives on the subclasses
> Method and Constructor. So we have more latitude than I thought.
> Which nudges me a little towards
>
> Object[] match(Object matchTarget, Object... additionalArgs)
>
> where match failure is reflected as null.
>
> This also nudges me a bit towards hiding matchers from
> getMethods() and friends (as we do with constructors).
>
>> And speaking of MethodHandles, will there be new
>> MethodHandles.Lookup.findMatcher , findDeconstructor, etc
>> methods? Or do you see them being looked up with the existing
>> find* methods?
>
> I had been assuming that we would use MethodHandle::findStatic for
> this.
>
>> We will then need some additional methods to describe the
>> bindings, so the
>> subtype of `Executable` has methods like `getBindings`,
>> `getAnnotatedBindings`,
>> `getGenericBindings`, `isDeconstructor`, `isPartial`, etc.
>> These
>> methods will
>> decode the `Matcher` attribute and its embedded attributes.
>>
>>
>> What does `getBindings` return? The MethodType describing the
>> bindings? A Class[] describing the types of the bindings?
>> Something else?
>>
>
> Class[] getBindings();
> Type[] getGenericBindings();
> AnnotatedType[] getAnnotatedBindings();
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-experts/attachments/20230308/9882b2bd/attachment-0001.htm>
More information about the amber-spec-experts
mailing list