Trouble inferring type of lambda

Howard Lovatt howard.lovatt at gmail.com
Mon Aug 23 05:49:44 PDT 2010


Thanks for the reply.

Whilst this will work, it is hardly desirable. Effectively the return
type of all lambdas has to 'free' variable then writing a method that
uses them is awkward, e.g.:

  @Override public <R, throws E> void forEach( final Method1<R,
Integer, E> method ) throws E {
    for ( int i = 0; i < values.length; i++ ) {
      final Integer oldValue = values[ i ];
      final R newValueTemp = method.call( oldValue );
      if ( newValueTemp instanceof Integer ) { values[ i ] = (Integer)
newValue; }
    }
  }

Not great!

Cheers,

 -- Howard.

On 23 August 2010 21:59, Maurizio Cimadamore
<maurizio.cimadamore at oracle.com> wrote:
> On 23/08/10 12:34, Howard Lovatt wrote:
>>
>> Thanks for the clarification, I think it *should* be a bug!
>>
>> In the meantime, what is the recommended idiom for writing such a
>> function.
>>
>
> You could try with:
>
> interface SortableList<T extends Comparable<? super T>> extends List<T> {
>
> <R, throws E> void forEach( Method1<R, T, E> method ) throws E;
>
> }
>
> this should do.
>
> Maurizio
>
>>  -- Howard.
>>
>> On 23 August 2010 21:15, Maurizio Cimadamore
>> <maurizio.cimadamore at oracle.com>  wrote:
>>
>>>
>>> On 23/08/10 12:02, Howard Lovatt wrote:
>>>
>>> Hi Mauritzio,
>>>
>>> I think it is a bug, like I said in the original post the 'return
>>> type' is 'NeverReturns' not void, which should be assignable to
>>> anything (including Integer). Scala and BGGA handle this case, they
>>> both have a 'NeverReturns' type (Scala and BGGA Nothing).
>>>
>>>
>>> Let me clarify - it is not a bug, according to the current spec; quoting
>>> from the latest formal spec describing lambda conversion [1]:
>>>
>>> "A divergent lambda expression such as #(){throw new AssertionError();}
>>> has no return value, and its body completes abruptly by reason of a
>>> throw with an AssertionError object. For the purpose of calculating
>>> the type of the lambda expression, the body of the lambda expression
>>> is void."
>>>
>>> [1] -
>>>
>>> http://mail.openjdk.java.net/pipermail/lambda-dev/attachments/20100212/af8d2cc5/attachment-0001.txt
>>>
>>> Maurizio
>>>
>>> Cheers,
>>>
>>>  -- Howard.
>>>
>>> On 23 August 2010 20:35, Maurizio Cimadamore
>>> <maurizio.cimadamore at oracle.com>  wrote:
>>>
>>>
>>> This is not a bug. You are trying to SAM convert the following lambda:
>>>
>>> #(x) { throws Exception(); }
>>>
>>> into the following target method:
>>>
>>> <throws E>  Integer call( Integer a1 ) throws E
>>>
>>> This is not possible, since the lambda expression is inferred to yield
>>> 'void' (no return expression found), while the target method returns
>>> Integer.
>>>
>>> Maurizio
>>>
>>>
>>>
>>> On 22/08/10 18:45, maurizio cimadamore wrote:
>>>
>>>
>>> On 22/08/2010 07:09, Howard Lovatt wrote:
>>>
>>>
>>>
>>> For:
>>>
>>>    public interface Method1<R, A1, throws E>     { public R call( A1 a1 )
>>> throws E; }
>>>
>>> and:
>>>
>>>    public<throws E>     void forEach( final Method1<Integer, Integer, E>
>>> method ) throws E { ... }
>>>
>>> The compiler has trouble with:
>>>
>>>     il.forEach( #( i ) { throw new Exception(); } ); // Need to catch
>>> checked exception
>>>
>>> Giving:
>>>
>>> lambdas/Main.java:34: method forEach in class IntList11 cannot be
>>> applied to given types
>>>        il.forEach( #( i ) { throw new Exception(); } ); // Need to
>>> catch checked exception
>>>          ^
>>>    required: Method1<Integer,Integer,E>
>>>    found: #void(?)(Exception)
>>>    where E is a type-variable:
>>>      E extends Exception declared in method
>>> <E>forEach(Method1<Integer,Integer,E>)
>>>
>>> Qualifying doesn't help:
>>>
>>>    Method1<Integer, Integer, Exception>     #( i ) { throw new
>>> Exception();
>>> }
>>>
>>> It gives:
>>>
>>> lambdas/Main.java:34: incompatible types; no instance(s) of type
>>> variable(s) ? exist so that #void(?)(Exception) conforms to
>>> Method1<Integer,Integer,Exception>
>>>        il.forEach( Method1<Integer, Integer, Exception>     #( i ) {
>>> throw
>>> new Exception(); } ); // Need to catch checked exception
>>>                    ^
>>>    required: Method1<Integer,Integer,Exception>
>>>    found:    #void(?)(Exception)
>>>
>>> Is the problem that the return type isn't expressible? It isn't really
>>> void, it is 'NeverReturns'.
>>>
>>>
>>>
>>>
>>> Uhmm the problem here seems more related with a failure in inference of
>>> the lambda parameter (the '?' that you are seeing). Again it would be
>>> helpful to see the declaration of the receiver class as well as the type
>>> of 'il'.
>>>
>>> Maurizio
>>>
>
>



-- 
  -- Howard.


More information about the lambda-dev mailing list