lambda explicit type declaration.
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Mon Nov 26 05:31:35 PST 2012
Rules could be more flexible and match those used for method references
- said that, some motivations behind current rules are:
*) the current rules are clearer as to what types are being used in a
lambda body in an implicit lambda (i.e. same types as the target type)
- note that a method reference doesn't have an analogous of a 'body' -
in the lambda it seems it's useful to know what the types of the
parameters will be, so that you know which members will be available on
them. If you add a lot of conversion rules, the type might be not
immediately obvious to the user.
*) More precise overload resolution - i.e. by putting explicit types you
will have the ability to effectively select which (among the set of
ambiguous methods) will be selected.
I also believe that inner classes were a bit in the back of our minds
when designing this - i.e. we basically wanted lambdas and anonymous
inner classes to be inter-changeable - it is true that once you add
method references to the picture you have another construct that behaves
slightly different, and that can be confusing too.
Maurizio
On 26/11/12 12:40, Sergey Kuksenko wrote:
> Hi,
>
> I'd like to ask about lambda with explicit parameters type declaration.
> There is a difference between method reference and lambda. Method
> reference parameters should be assignable to types of functional
> interface method parameters, but lambda parameters should be the same as
> types of functional interface method parameters. Different rules leads
> to inconsistency between lambda & method references (it is my opinion -
> I understand that others may think such inconsistency is ok). I think
> such strict rule for lambda makes less value of the ability to declare
> lambda parameter types explicitly.
>
> Let's consider a couple examples.
>
> 1. Well known "boxed value equals" problem.
>
> Comparator<Integer> wrong_comparator
> = (x, y) -> (x < y) ? -1 : ((x == y) ? 0 : 1);
>
> And I expecting more similar bugs in the new code with lambdas,
> especially in places where generic boxed and specialised primitive
> functional interfaces are used. Developers will misthink, misprint,
> misevaluate type inference ....
>
> The best (IMO) way to fix the problem is not allowed right now:
>
> Comparator<Integer> fixed_comparator
> = (int x, int y) -> (x < y) ? -1 : ((x == y) ? 0 : 1);
> // won't compile.
>
> Other ways to fix it are not such simple like:
>
> Comparator<Integer> fixed_comparator = (a,b) -> {
> int x = a;
> int y = b;
> return (x < y) ? -1 : ((x == y) ? 0 : 1);
> };
>
>
> 2. Fields access.
>
> We have two classes:
>
> class A {
> public int foo = 42;
> }
>
> class B extends A {
> public int foo = 43;
> }
>
> and two mappers:
>
> Mapper<Integer, A> defoogaringA0 = a -> a.foo;
> Mapper<Integer, B> defoogaringB0 = a -> a.foo;
>
> Results are different:
> System.out.println( defoogaringA0.map(new B())); // print 42
> System.out.println( defoogaringB0.map(new B())); // print 43
>
> and it is the results should be. But we don't have a convenient way to
> manage it. Like lets create a method:
>
> static int defoo(A a) {
> return a.foo;
> }
>
> and two mappers:
>
> Mapper<Integer, B> defoogaringB1 = Test::defoo;
> Mapper<Integer, A> defoogaringA1 = Test::defoo;
>
> System.out.println( defoogaringA1.map(new B())); // print 42
> System.out.println( defoogaringB1.map(new B())); // print 42
>
> So if I have a stream of <B> elements - I can't process them with lambda
> accepting type A, because of even explicitly declared type should be the
> same as inferred - <B>. The only way is using method references or
> expressions like:
>
> Mapper<Integer, B> defoogaringB2 = (B a) -> ((A)a).foo;
>
> System.out.println( defoogaringB2.map(new B())); // print 42
>
> But again I can't write a simple expression:
>
> Mapper<Integer, B> defoogaringB2 = (A a) -> a.foo; // won't compile
>
>
>
>
>
>
More information about the lambda-dev
mailing list