This is part of a larger problem, and I don't think point fixes are
really the answer here. For this reason (and others), any sort of "type
more things as void" is on hold for now. Here's a sketch of the
motivation, which comes from Valhalla.
A big part of Valhalla is unifying primitives and references. This means
(yay) that we can say goodbye to IntPredicate and friends, since we can
have:
interface IntPredicate extends Predicate<int> { ... }
In turn, we can also start to unify Predicate into Function:
interface Predicate<T> extends Function<T, boolean> { ... }
But Consumer is a roadblock, because void is not a type. We'd like to
have a path to getting to this unification; tinkering with treating more
statements as void expressions could make this harder.
On 9/26/2021 3:11 PM, Remi Forax wrote:
There is a bad interaction between a lambda and a switch expression,
a lambda allows its expression to be typed void but a switch expression can not
be typed void,
so the following code does not compile
sealed interface I permits A, B {}
record A() {}
record B() {}
public Optional<A> findOneA(List<I> list) {
return list.stream()
.<A>mapMulti((i, consumer) -> switch(i) {
case A a -> consumer.accept(a);
case B b -> {}
})
.findFirst();
}
This bug occurs for with any methods that takes a Consumer has parameter (so
stream.forEach/peek, Iterator.forEachRemaining etc).
The workaound is to add a pair of curly braces around the switch to transform
it to a switch statement.
For me, it should be possible to have a switch expression typed void. This is a
backward compatible change given that the code does not compile otherwise.
regards,
Rémi