I think this is the key observation:
And because patterns can nest,*this “right edge” can occur placed inside a 
sub-pattern*, which lets us smuggle guards
anywhere we like, with a little care:  P&(var x when g(x))&Q.

Our diffidence about a "Patterns + Guards" construct is that forcing all the guards to the end seems too constraining; I was never convinced that P & G & Q is freely substitutible in practice for P & Q & G (even if the differences are only "nonfunctional").  But, if we posit, as Guy did:

    (&&) :: Pattern -> BoolExpr -> Pattern
    (&) :: Pattern -> Pattern -> Pattern

then, using the existing precedence of && and &, then "P and g and Q" can be expressed as (P && g) & Q, because (P&&g) is a pattern, which can be ANDed with pattern Q. Then:

    if (x instanceof P && g)

parses using existing rules as the boolean expression

    if ( (x instanceof P) && g )

by ordinary operator precedence, and

    if (x instanceof (P && g))

parses as the match of x to the guarded pattern (P && g), which in this case is silly but harmless, but may be useful when we are &ing more patterns together.  And:

    case P && g:

is an ordinary pattern case with the pattern P-guarded-by-g, no special switch magic.

As John says, we don't need & immediately, but there's room for it when we need it with the semantics we expect.

What this doesn't give us is a simple form for

    case <boolean expression>

in a pattern switch, but there are plenty of ad-hoc ways to do that:

    case boolean(e):
    case true(e):
    case &&e:
    case if e:
    case _ && e:


Reply via email to