> 2. Positioning of guards
We received several forms of feedback over the form and placement of guarded
patterns. Recall that we define a guarded pattern to be `P && g`, where P is a
pattern and g is a boolean expression. Guarded patterns are never total. Note
that we had a choice of the guard being part of the pattern, or being part of
the `case` label; the current status chooses the former. (Part of our
reasoning was that there might be other partial pattern contexts coming, and we
didn’t want to solve this problem each time. (For intsanceof, it makes no
difference.) )
I am prepared to reconsider the association of the guard with the pattern, and
instead treat it as part of the case. This is expressively weaker but may have
other advantages.
Additionally, people objected to the use of &&, not necessarily because
“keywords are better”, but because of the potential confusion should we ever
choose to support switch over boolean, and because the && did not stand out
enough as turning a total pattern into a partial one. What the alternative
looks like is something like:
switch (x) {
case Foo(var x, var y)
when x == y -> A;
case Foo(var x, var y) -> B;
}
Here, `when` (bike shed to be painted separately) is a qualifier on the case,
not the pattern. A total pattern with a `when` is considered a partial case.
This simplifies patterns, and moves the complexity of guards into switch, where
arguably it belongs.
The loss of expressiveness is in not allowing nested patterns like:
P(Q && guard)
and instead having to move the guard to after the matching construct. Some
users recoiled at seeing guards inside pattern invocations; it seemed to some
like mixing two things that should stay separate. (For unrolling a nested
pattern, `case P(Q)` where Q is not total unrolls to `case Pvar alpha) when
alpha instanceof Q`.)