Lambda and JSR 292 method handle
Howard Lovatt
howard.lovatt at iee.org
Sat Jan 2 11:42:40 PST 2010
Neal,
Specifically in response to your example:
*List<#String()> alphabet() {
return lazify(**Arrays.asList("a", "b", "c")**);
}*
*
*
This would be:
*List<Callable$0<String>> alphabet() { ... }
*
*
*
Therefore no problem.
Also note that the 'cast' classes are generated on demand, therefore no
explosion of types.
-- 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