SAM identity or at least equals/hashCode
Ali Ebrahimi
ali.ebrahimi1781 at gmail.com
Tue Jun 21 07:48:12 PDT 2011
Hi, I know that.
I think we can convert all statefull lambdas to stateless ones in
desugering phase.
Ali ebrahimi
On Tue, Jun 21, 2011 at 5:57 PM, Brian Goetz <brian.goetz at oracle.com> wrote:
> The compiler desugars the lambda to a method that has two parameters. SAM
> converting that method to one that has no parameters can be accomplished in
> a number of ways -- generating bytecode for the method that does the
> currying, MethodHandle.insertArguments, etc.
>
>
> On 6/21/2011 10:20 AM, Ali Ebrahimi wrote:
>
>> Hi,
>> how do you handle it if you have more than one captured (bound) state?
>>
>> public Adder adderGenerator(int x, int y) { return #{ -> x + y} };
>>
>> Ali Ebrahimi
>> On Tue, Jun 21, 2011 at 5:36 PM, Peter Levart<peter.levart at marand.si>**
>> wrote:
>>
>> On 06/21/11, Brian Goetz wrote:
>>>
>>>> If you want to refer to the object instance that is the result of
>>>>>> SAM conversion, call that the SAM instance or the SAM object --
>>>>>> which is an object. (You can't assume much about its identity --
>>>>>> the compiler will likely make sure that all instances of
>>>>>> "stateless" lambdas are really the same object, a la the
>>>>>> "Flyweight" pattern.)
>>>>>>
>>>>>
>>>>> Only stateless? Why?
>>>>>
>>>>
>>>> Lambdas can capture final local variables. Consider:
>>>>
>>>> public IntFactory constGenerator(int x) { return #{ -> x } };
>>>>
>>>>
>>> This is exactly the use case I'm talking about. One would want that
>>>
>>> constGenerator(12).equals(**constGenerator(12)) would evaluate to true
>>> and
>>> constGenerator(12).equals(**constGenerator(13)) would evaluate to false
>>>
>>> event though the instances of two SAM objects returned from two
>>> invocations
>>> of method:
>>>
>>> constGenerator(12)
>>>
>>> are not the same instance, they could be equal.
>>>
>>> Clients will call the resulting IntFactory with
>>>> foo.make()
>>>> and expect an int to come back. The SAM-converted lambda is an object,
>>>> it has to have a nilary make() method, that method has captured state x,
>>>> so where do we store the captured state?
>>>>
>>>>
>>> I belive you (could) generate a static method with one formal parameter:
>>>
>>> private static int lambda$1(Integer p1) { return p1; }
>>>
>>> ...then obtain a MethodHandle for it, say: lambda$1Mh
>>> ...then capture the final x: lambda$1BoundMh = lambda$1Mh.bindTo(x);
>>>
>>> now the SAM-converted lambda object has a reference to lambda$1BoundMh.
>>> It
>>> uses it to delegate the invocation of it's nilary make() method to. So
>>> why
>>> could it not use it to delegate equals/hashCode methods too? The
>>> prerequisite is of course that MethodHandle(s) define meaningfull
>>> equals/hashCode methods that take into account the captured (bound) state
>>> and any final target method identity too. That's what I had in mind.
>>>
>>> For the above example, lambda$1BoundMh would implement equals/hashCode in
>>> terms of delegating to bound Object (Integer in our case) and to the
>>> wrapped
>>> MH lambda$1Mh. The final lambda$1Mh would implement equals/hashCode in
>>> terms
>>> of target lambda$1 method signature.
>>>
>>> Now, I don't know much about MHs and how they are implemented and
>>> optimized
>>> in the VM, so perhaps such scheme would defeat those optimizations. Or is
>>> it
>>> still possible?
>>>
>>> Regards, Peter
>>>
>>>
>>>
>>>
>>>
>>
More information about the lambda-dev
mailing list