Why is this type inference not working with this Lambda expression scenario?

后端 未结 6 762
小蘑菇
小蘑菇 2020-12-24 01:23

I have a weird scenario where type inference isn\'t working as I\'d expect when using a lambda expression. Here\'s an approximation of my real scenario:

stat         


        
6条回答
  •  既然无缘
    2020-12-24 02:07

    Inference on lambda parameter type cannot depend on the lambda body.

    The compiler faces a tough job trying to make sense of implicit lambda expressions

        foo( value -> GIBBERISH )
    

    The type of value must be inferred first before GIBBERISH can be compiled, because in general the interpretation of GIBBERISH depends on the definition of value.

    (In your special case, GIBBERISH happens to be a simple constant independent of value.)

    Javac must infer Value first for parameter value; there's no constraints in context, therefore T=Object. Then, lambda body true is compiled and recognized as Boolean, compatible with T.

    After you made the change to the functional interface, the lambda parameter type does not require inference; T remains uninfered. Next, the lambda body is compiled, and the return type appears to be Boolean, which is set as a lower bound for T.


    Another example demonstrating the issue

     void foo(T v, Function f) { ... }
    
    foo("", v->42);  // Error. why can't javac infer T=Object ?
    

    T is inferred to be String; the body of lambda did not participate in the inference.

    In this example, javac's behavior seems very reasonable to us; it likely prevented a programming error. You don't want inference to be too powerful; if everything we write compiles somehow, we'll lose the confidence on compiler finding errors for us.


    There are other examples where lambda body appears to provide unequivocal constraints, yet the compiler cannot use that information. In Java, the lambda parameter types must be fixed first, before the body can be looked at. This is a deliberate decision. In contrast, C# is willing to try different parameter types and see which makes the code compile. Java considers that too risky.

    In any case, when implicit lambda fails, which happens rather frequently, provide explicit types for lambda parameters; in your case, (Value value)->true

提交回复
热议问题