Brian Goetz brian.goetz at
Sat Mar 6 17:22:29 UTC 2021

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:

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the amber-spec-experts mailing list