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

Reply via email to