On 13/04/2020 12:28, Ilija Tovilo wrote:
It would be possible for the blocks to return values (though not with
the return keyword).
[...]
We can't do everything at once.
Then why not introduce the match expression first, and add block
expressions (as a general concept) later? That way, we don't need all
the special restrictions on when to use them, and can work out a
consistent set of rules for them which can apply language-wide, rather
than being constrained later by decisions we make half-implementing them
now.
The ability to use them with short closure syntax would be very
interesting, if the scoping/capture rules could be agreed.
it makes *all* the control flow blocks in Rust feel more natural to
developers coming from other languages.
Same thing here. If you don't use the result value, it looks just like
the switch. That's why I'd feel odd to require a semicolon.
Not really. In Rust, it's about making a whole bunch of control
structures, which are already consistent with each other, more user
friendly (but still consistent). In your proposal, it's about making one
specific control structure look slightly more like other syntaxes in the
same language, by adding a special case which applies nowhere else.
To be specific, in PHP, there is no "omitted semicolon" at the end of
"if ($x) { y(); }" - that is just how the syntax is defined. There's no
need to have a parser rule to allow it to look like C or Java, because
it already does.
This code is parsed like this:
```
match($x) { 1 => ['foo', 'bar'] }
[0];
```
* statement list
* match expr
* array literal
Note that we can't have ambiguous grammar since Bison would
immediately expose it.
I'm not sure what you mean by "we can't have ambiguous grammar" - the
code above *is* ambiguous, in that it could be defined to mean one of
two things; what you've shown is which definition your implementation
defines.
That resolution makes sense for that example, but consider some others:
// As proposed, parsed as two meaningless expression-statements; as a
normal expression, would select and then invoke a callable
match($x) { 1 => 'print', 2 => 'var_dump' }
($x);
// Invalid under the proposed rule, but a valid method call if match was
always a normal expression
match($x) { 1 => new Foo, 2 => new Bar }
->doSomething();
To be fair, the same limitation exists for closures, where this is invalid:
function($x) { echo $x; } ("Hello");
and you have to write this instead:
(function($x) { echo $x; }) ("Hello");
So I guess the above would follow the same rule to force expression context:
(match($x) { 1 => 'print', 2 => 'var_dump' })($x);
(match($x) { 1 => new Foo, 2 => new Bar })->doSomething();
The only downside is that omitting the parentheses wouldn't be an error,
as with the closure case, it would just silently do nothing, which might
be rather confusing. Dropping the special semicolon handling would mean
it either did the expected thing or gave a parse error straight away.
Regards,
--
Rowan Tommins (né Collins)
[IMSoP]
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php