On Tue, Apr 28, 2020, at 10:31 AM, Rowan Tommins wrote:
> On Tue, 28 Apr 2020 at 16:10, Bob Weinand <bobw...@hotmail.com> wrote:
> 
> > I think you should first think about why the "case" needs to exists at
> > all. In particular it exists to distinguish goto labels from the case
> > expressions in switch. With match, match restricting statements (and thus
> > goto labels) into { brackets }, it now is not necessary to do such a
> > distinction and we can get rid of the extra token.
> >
> 
> 
> That may be obvious if you're used to writing parsers, but to users, the
> case keyword is simply how switch statements work. Removing it just makes
> the new statement look less familiar and isn't justified by the aims stated
> in the RFC.
> 
> 
> 
> > "=>" is logical as well, we use the return value of the expressions (see
> > fn() and array syntax), the colon is exclusively used for pure statement
> > boundaries.
> >
> 
> 
> You've missed the context of my e-mail: I was explicitly discussing a
> hypothetical syntax that *doesn't* resolve to a value, and where the colon
> *is* introducing a statement not an expression.
> 
> 
> 
> > The comma is necessary for the expression syntax at least (consider
> > match($a) { 1 => 2  + 2 + 2 => 3 } - is this now match($a) { 1 => 2, (2 +
> > 2) => 3 } or match ($a) { 1 => (2 + 2), +2 => 3 } ?) You may argue to make
> > it optional behind a statement block though.
> 
> 
> 
> Again, expressions are explicitly out of scope for this thought experiment.
> As such, the result of every case is delimited either by a closing brace or
> a semi-colon, and the above example is simply a syntax error.
> 
> 
> As I've said many times now, I really like the match expression, with the
> current syntax, as a pure expression. I was explicitly addressing the
> question of why I think a straight-forward switch replacement would not
> look the same if we weren't trying to squeeze two features into one syntax.
> 
> Regards,
> -- 
> Rowan Tommins
> [IMSoP]


I agree that there seems to be two entirely different problem spaces being 
smushed together here, which is creating a problem (both for the code and for 
the discussion).  Which... suggests we really should try to split them up.

To that end, I'm going to refer to them as rustmatch (an expression that only 
supports expressions and returns things; basically a fancier alternative to 
ternary) and switchtng (a procedural branching statement that is basically 
switch but with the lessons of the 40 years since C switch was invented, which 
PHP blindly inherited) to avoid privileging one or the other.

Based on the current RFC voting, it seems like there's strong interest in 
rustmatch, using the syntax currently proposed:

$expressionResult = match ($condition) {
    1, 2 => foo(),
    3, 4 => bar(),
    default => baz(),
};

I'm calling this "rustmatch" because its semantics and syntax are largely 
borrowed from Rust's match expression 
(https://aminb.gitbooks.io/rust-for-c/content/control_flow/index.html).  (Yes, 
Rust supports multi-line expressions but it does all over the place, which is a 
separate issue.)

The other is what, I think, Ilja was originally trying to do, which is a more 
Go-style switch (https://gobyexample.com/switch) than a C-style switch.  That 
is, still a procedural construct but less bug-prone.

One issue that was discussed a few weeks ago, and led to the current syntax, 
was too many variations within the switch syntax; of course, trying to do it 
all in one syntax is perpetuating that problem.  However, I think Rowan has 
suggested a syntax that may be sufficiently self-documenting.  To wit, 
independent of rustmatch (above):

switch ($foo) {
  case 1: {
    Many statements here.
  }
  case 2: {
    Many statements here.
  }
}

The curly braces are already understood by most PHPers to mean "a block of 
statements", and so it's a logical jump in this case.  As Rowan suggests, the 
{} imply a break.  To keep it simple we should probably not allow mixing and 
matching in a single switch.  Either list-style (break required) or {}-style 
(break implied).

That handles break; the other problems listed in the RFC for switch are:

* weak comparison
* Inexhaustive
* No return

The no-return is only an issue for the expression-centric approach, which 
belongs to rustmatch, and thus in a split approach is off topic.  If you want 
multi-prong branching that evaluates to a returned value... use the rustmatch 
option and be done with it, go away.

For the other two, would a simple "strict" keyword be acceptable to people?  
The net result being:

switch strict ($foo) {
  case 1: {
    Many statements here.
  }
  case 2: {
    Many statements here.
  }
}

That does a strict type comparison on $foo, triggers a warning/error/whatever 
if nothing matches (default is still supported of course), and the curly braces 
replace break.  It can NOT return anything, but that's OK, because it's a flow 
control construct, not an expression.  Never the twain shall meet.

If this seems reasonable to folks, particularly Ilja, I'd suggest pulling the 
current vote/letting it expire, and then reintroducing it as *just* an 
expression, with single-expressions only, semi-colon required always, and an 
implicit default match value of true (as the current polls very strongly 
indicate; thank you Ilja for including the extra data gathering).  Then in 
parallel introduce a second RFC that adds the strict keyword and {} 
alternative, and *nothing else*.  Let that have its own, separate vote.

Based on the current voting I strongly suspect the more limited match 
expression v2 would pass easily.  I don't know if the strict switch would pass 
or not, but it would at least be able to get a fair shake on its own without 
trying to do double-duty as an expression and a statement at the same time, 
which the current RFC is trying to do.

--Larry Garfield

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to