Lambda and JSR 292 method handle

Howard Lovatt howard.lovatt at iee.org
Sat Jan 2 11:30:12 PST 2010


Neal and Zdenek,

I have update the blog in line with your suggestions - thanks.

 -- Howard.

2009/12/30 Neal Gafter <neal at gafter.com>

> On Tue, Dec 29, 2009 at 11:32 PM, Howard Lovatt <howard.lovatt at iee.org>wrote:
>
>> Neal,
>>
>> Good points, the first:
>>
>>
>> >
>>
>> > List<? *extends* #String(Object)>
>> >
>>
>>
>> > to a value of type
>> >
>>
>> > List<? *extends* #Object(String)>
>> >
>>
>>
>>
>> Is easily fixable by having the reified versions extend the generic
>> versions with a special case for primitives, i.e.:
>>
>> *public* *abstract* *class* Callable$Int *implements* Callable$0<Integer> {
>>   *public* *abstract* *int* callInt();
>>   @Override *public* *final* Integer call() { *return* callInt(); }}
>>
>> That answer is nonresponsive to my question.
>
>
>> > Also, there need to be subtype relations in both
>> > directions between your Callable$0<String> and
>> > Callable$String but that is impossible because they are
>> > distinct interfaces. If you try to provide the subtype
>> > relations in just one direction, things quicky get out of
>> > hand (i.e. an exponential explosion in direct
>> > superinterfaces of the generated interfaces) when there
>> > are multiple lambda arguments.
>>
>> The above modification to implement Callable$... solves this problem in
>> one direction and the other is via 'cast' methods. The idea was that the
>> 'cast' methods are loader generated, though re-reading my post I didn't make
>> this clear (sorry).
>>
>
> My point is that the subtypes in one direction generate an inheritance
> hierarchy that gets out of hand, and the cast methods in the other direction
> don't actually work.
>
> To take a specific simple example of the latter issue, consider a method
> that returns a generic list of functions:
>
> *<T> List<#T()> lazify(List<T> data) {
>     List<#T()> result = new ArrayList<#T()>();
>     for (T t : data) result.add(#()t); // adds element of type
> Callable$0<T>
>     return result;
> }
> *
>
> the list that is returned contains lambdas of type Callable$0<T>.  Then we
> call it on some data
>
> *List<#String()> alphabet() {
>     return lazify(**Arrays.asList("a", "b", "c")**);
> }
> List<#String()> **alphabet **= **alphabet**();*
>
> now alphabet contains a List whose elements are of type Callable$0<String>
> (but the compiler probably thinks those elements are of type
> Callable$String).  So we pull a datum out of it.
>
> *#String() firstLetter = **alphabet**.get(0);
> *
>
> Now we've assigned something of type Callable$0<String> to something of
> type Callable$String.  Where in the execution of this code did the "cast"
> occur?
>
> I am making the assumption that these 'casts' are rare and therefore in
>> practice you won't get an explosion of 'cast' methods.
>>
>
> As much as I take issue with your assumption, I am more concerned about
> correctness than performance.
>
> -Neal
>
>
> ______________________________________________________________________
> This email has been scanned by the MessageLabs Email Security System.
> For more information please visit http://www.messagelabs.com/email
> ______________________________________________________________________
>



-- 
 -- Howard.


More information about the lambda-dev mailing list