Note too that we also considered the case (heh) of a switch with _zero_
selectors, as a replacement for chains of if-else that all produce a
value to be consumed in a uniform way:
String s = switch {
case when e1 -> x;
case when e2 -> y;
default -> z;
}
This obviously doesn't have the problems I outlined with multi-selector,
but it is definitely "weirder". It seeks to capitalize on the strength
reduction of switch relative to an if-else chain, but I'm also not
convinced this one carries its weight.
On 9/27/2023 10:18 AM, Brian Goetz wrote:
[ dropping amber-dev ]
Yes, we've discussed this before. A switch could have multiple
selector values:
switch (a, b)
and cases could be structured similarly:
case (P, Q):
All of this isn't hard. The real question is, does it result in
better or worse code? My sense is that it look really pretty in the
simple examples, but as the number of selectors and the size of the
patterns increases, it is likely to become an unreadable soup. So
that's a concern.
As an example of a "the simple cases are very pretty", I give you a
world-class FizzBuzz:
Function<Integer, String> fizzbuzz =
x -> switch (x % 3, x % 5) {
case (0, 0) -> "FizzBuzz";
case (0, _) -> "Fizz";
case (_, 0) -> "Buzz";
default -> Integer.toString(x);
};
(I might have gotten my Fizz and Buzz backwards, I didn't bother to
look it up.)
<sarcasm>
I see the appeal in "Java is the #1 language for writing FizzBuzz",
but I am not sure this is the stewardship rubric we are looking for :)
</sarcasm>
Another problem (and this one is of our own making) is that comma
already means something in cases. So
case 0, 1
means something subtly different from
case (0, 1)
which is not particularly nice. Yes, the type checker will
disambiguate for you, but we are not used to both `X` and `(X)` being
valid in the same context but meaning different things. (Worse, when
you combine these where you have multiple tuple patterns on one case,
it's even more case soup.)
So I put this one in the category of "simple enough to specify and
implement, has obvious motivating use cases, but not sure it actually
improves the language."
On 9/27/2023 10:03 AM, Remi Forax wrote:
Hi recently Clément BOUDEREAU has reported a bug on amber-dev and unrelated to
that bug,
taking a look to the code I've noticed this
int compareTo(final Value<T> o) {
return switch (new Tuple<>(this, o)) {
case Tuple<Value<T>, Value<T>>(Value.Infinite<T> _,
Value.Infinite<T> _) -> 0;
case Tuple<Value<T>, Value<T>>(Value.Infinite<T> _,
Value.Fixed<T> _) -> 1;
case Tuple<Value<T>, Value<T>>(Value.Fixed<T> _,
Value.Infinite<T> _) -> -1;
case Tuple<Value<T>, Value<T>>(Value.Fixed<T> fst, Value.Fixed<T>
snd) ->
fst.value.compareTo(snd.value);
};
}
Here what Clément want is to match two values (here, "this" and "o") but the
only way to do that is to wrap them into a pair (here named Tuple),
Should we not provide a way to match several values natively ?
Something like
int compareTo(final Value<T> o) {
return switch (this, o) {
case (Value.Infinite<T> _, Value.Infinite<T> _) -> 0;
case (Value.Infinite<T> _, Value.Fixed<T> _) -> 1;
case (Value.Fixed<T> _, Value.Infinite<T> _) -> -1;
case (Value.Fixed<T> fst, Value.Fixed<T> snd) ->
fst.value.compareTo(snd.value);
};
}
regards,
Rémi