Trouble inferring type of lambda
Howard Lovatt
howard.lovatt at gmail.com
Sun Aug 22 22:31:09 PDT 2010
Hi Maurizio,
As a bit of background I was thinking of giving a talk at the Sydney
JUG, nothing arranged yet - just a thought, on the likely Java 7
features, hence the writing style of the code below. All the examples
I am having trouble with, except
String.String.CASE_INSENSITIVE_ORDER.compare( String, String ) - which
is obvious anyway, are covered in the code below. Hence this one email
covers all. I have also attached the files and the compile/run script.
public interface Method1<R, A1, throws E> { public R call( A1 a1 ) throws E; }
public interface SortableList<T extends Comparable<? super T>> extends List<T> {
extension void sort() default Collections.sort;
<throws E> extension void forEach( Method1<T, T, E> method ) throws
E default Trait.forEach;
static class Trait {
public static <T extends Comparable<? super T>, throws E> void forEach(
final SortableList<T> self, final Method1<T, T, E> method )
throws E {
for ( int i = 0; i < self.size(); i++ ) {
final T oldValue = self.get( i );
final T newValue = method.call( oldValue );
self.set( i, newValue );
}
}
}
}
public class IntList11 extends AbstractList<Integer> implements
SortableList<Integer> {
private final int[] values = new int[] { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
@Override public Integer get( final int index ) { return values[ index ]; }
@Override public Integer set( final int index, final Integer newValue ) {
final int old = values[ index ];
values[ index ] = newValue;
return old;
}
@Override public int size() { return values.length; }
@Override public <throws E> void forEach( final Method1<Integer,
Integer, E> method ) throws E {
// for ( int i = 0; i < size(); i++ ) {
for ( int i = 0; i < values.length; i++ ) {
// final Integer oldValue = get( i );
final Integer oldValue = values[ i ];
final Integer newValue = method.call( oldValue );
// set( i, newValue );
values[ i ] = newValue;
}
}
}
public class Main {
public static void main( final String... notUsed ) throws Throwable {
// coin-dev
// TODO
// lambda-dev
lambdas();
// extensionMethods(); - no runtime at present
exceptionTransparency();
// mlvm-dev
// TODO
}
private static void lambdas() throws Throwable {
// SAM conversion, shorthand for an instance of an anonymous inner class
// Syntax may change to { args -> body }
// final Runnable r1 = new Runnable() {
// public void run() { out.println( "Start" ); }
// };
final Runnable r1 = #() { out.println( "Start" ) };
r1.run();
// Can have complex bodies as well as 'expressions', seperated by
; and ; on last line
// See below for alternative
final Runnable r2 = #() {
int sum = 0;
for ( int i = 1; i <= 4; i++) { sum += i; }
out.println( "Sum 4 = " + sum );
};
r2.run();
// Can be an abstract class
abstract class AbstractRun implements Runnable {
AbstractRun() { throw new NullPointerException(); }
}
try {
final AbstractRun r3 = #() { out.println( "Never called" ) };
r3.run();
} catch ( final NullPointerException notUsed ) {
out.println( "Exception in constructor" );
}
// Arguments and Target Typing
// Argument type is ActionEvent
final ActionListener al1 = #( notUsed ) { out.println(
"ActionListener lambda 1 called" ) };
final JButton b1 = new JButton();
b1.addActionListener( al1 );
b1.doClick();
// Can type arguments but not return type, little point though - see below
final ActionListener al2 = #( final ActionEvent notUsed ) {
out.println( "ActionListener lambda 2 called" )
};
b1.addActionListener( al2 );
b1.doClick();
// More usefully you can add final.
final ActionListener al3 = #( final notUsed ) {
out.println( "ActionListener lambda 3 called" )
};
// Method References, syntax like Javadoc
b1.addActionListener( Main#print( ActionEvent ) );
b1.doClick();
// Can be bound to an object
class Print {
void print( final ActionEvent notUsed ) { out.println(
"Main.Print.print method called" ); }
}
b1.addActionListener( new Print()#print( ActionEvent ) );
b1.doClick();
// this
out.println( "Class = " + al3.getClass() +
", instanceof ActionListener = " + (al3 instanceof ActionListener) +
", instance of enclosing class (Main) = " + (al3 instanceof Main) );
// Effectively final
// No use to me, but others like it!
String s = "Effectively final"; // not *declared* final, but
effectively final
final Callable<String> cs = #() { s };
out.println( cs.call() );
}
private static void print( final ActionEvent notUsed ) {
out.println( "Main.print method called" );
}
private static void extensionMethods() {
final IntList11 il = new IntList11();
out.println( il );
il.sort();
out.println( il );
}
private static void exceptionTransparency() {
final IntList11 il = new IntList11();
out.println( il );
// il.forEach( #( i ) { 2 * i } ); // No exception; no try block -
has syntax error
il.forEach( #( i ) { return 2 * i; } ); // No exception, no try block
out.println( il );
// try {
il.forEach( #( i ) {
if ( i < 3 ) { throw new Exception(); }
return i * i;
} ); // Should need to catch checked exception!
// } catch (final Throwable notUsed) {
// out.println( "Exception caught" );
// }
out.println( il );
}
}
Keep up the good work,
-- Howard.
On 23 August 2010 03:45, maurizio cimadamore
<maurizio.cimadamore at oracle.com> 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