Contexts for Defining Lambda Expressions – Functional-Style Programming


13.14 Contexts for Defining Lambda Expressions

In this section, we summarize the main contexts that can provide target types for lambda expressions and method references.

Declaration and Assignment Statements

Ample examples of defining lambda expressions and method references in this context have been presented throughout this chapter. As we have seen earlier, the target type is inferred from the type of the assignment target—that is, the functional interface type being assigned to on the left-hand side of the assignment operator.

Click here to view code image

DoubleFunction cToF = x -> 1.8 * x + 32.0;           // double -> double
ToIntFunction<String> lenFunc1 = s -> s.length();    // String -> int
ToIntFunction<String> lenFunc2 = String::length;     // String -> int
lenFunc1 = s -> Integer.parseInt(s);                 // String -> int
lenFunc2 = Integer::parseInt;                        // String -> int

Method and Constructor Calls

We have seen several examples where a lambda expression is passed as an argument in a method or constructor call. The target type is the functional interface type of the corresponding formal parameter.

Click here to view code image

List<Integer> numbers = Arrays.asList(1, 2, 3);
numbers.forEach(i -> System.out.println(i));   // Target type: Consumer<Integer>
numbers.forEach(System.out::println);

Expressions in return Statements

The expression in a return statement can define a lambda expression (or a method reference) whose target type is the return type of the method. The method below returns a function of type int -> int:

Click here to view code image

static IntUnaryOperator createLinearFormula(int a, int b) {
  return x -> a * x + b;      // int -> int
}
// Client code:
IntUnaryOperator y = createLinearFormula(10, 5);  // 10 * x + 5
y.applyAsInt(2);                                  // 25

Ternary Conditional Expressions

For lambda expressions defined in a ternary conditional expression, the target type is inferred from the context of the ternary conditional expression.

In the first ternary conditional expression below, the target type for the lambda expressions that are operands is inferred from the target of the assignment statement, which happens to be an IntUnaryOperator interface.

Click here to view code image

int ii = 10;
IntUnaryOperator iFunc1 = ii % 2 == 0 ? i -> i * 2 : j -> j + 1;   // int -> int
iFunc1.applyAsInt(4);                                              // 8
//IntUnaryOperator iFunc2 = ii % 2 == 0 ? i -> i * 2
//                          : s -> Integer.parseInt(s);   // Compile-time error!

In the second ternary conditional expression above, the code does not compile because the type String -> int of the lambda expression that is the second operand is not compatible with the type int -> int of the assignment target.

Leave a Reply

Your email address will not be published. Required fields are marked *