Hi Ilija,
Ilija Tovilo wrote:
I share others' concern that it is inconsistent with PHP's
existing statements
Can you elaborate on what exactly the concerns are?
Well, I don't think we have any other expressions that are also
statements with very slightly different syntax, and in this RFC you
propose that the expression and statement forms have different behaviour
(expression doesn't support blocks) despite looking the same. So it's
neither consistent with other statements and expressions, nor is it
internally consistent.
It is a shame you don't suggest taking this opportunity to add
pattern matching.
My main concern here is just complexity. There's so much to consider.
We need to think well about each pattern, how it should work, what it
should look like, how it should be implemented, etc. Furthermore
pattern matching usually isn't restricted to the match expression.
There's often pattern matching for `if`, `while`, `foreach`, function
params, normal assignment, etc. So I don't think it should be mixed
with this RFC. IMO if we implement pattern matching we should make it
available for all of these cases.
We already have a limited kind of pattern matching in PHP, destructuring
assignment for arrays. You can use it on the left-hand side of any
assignment, and also in `foreach`. This pattern can even fail to match,
but you get an E_NOTICE instead of a Throwable.
It might be nice to have it in some other places, but it isn't
necessary. Haskell itself only has it in function definitions,
assignments and `case` expressions IIRC, and the former two uses are
essentially sugar over use of `case` anyway.
Why not take what we have here and support it in `match` too, but with
slightly stricter rules so that cases that would otherwise trigger an
E_NOTICE lead to choosing a different branch? It would make both our
existing pattern-matching and `match` more powerful! Consider
interacting with some JSON API:
match (json_decode($response)) {
['error' => ['code' => $code, 'msg' => $msg] => {
throw new Exception($msg, $code);
},
['result' => $result] => {
return $result;
},
// No default, so if the JSON doesn't fit this expected format, an
error is thrown! :)
}
This is just a quick example that came to mind, which doesn't really use
the full potential available here.
Another kind of existing pattern matching is arguably `catch` in
exception handling, so maybe we could also have `SomeClass $obj` as a
pattern, though that syntax would lead to questions of whether things
like `?SomeClass`, `int` and `SomeClass|SomeClass2` should work…
Using a keyword prefix (e.g. `let`) in future means we end
up with two kinds of arm (one with === behaviour, one with
pattern-matching behaviour), but wouldn't it be simpler to
have just one?
I personally don't think so. Consider this case:
```
$x = 10;
$y = 20; // This variable is unused
match ($x) {
$y => { // Always true
echo $y; // Outputs 10
},
}
```
`$y` is an identifier pattern and it always matches and assigns the
given value to the variable. This is rather confusing. A keyword like
`let` would make it more obvious that you're using a pattern. I'd also
suspect that it's more common to pass expressions to the lhs of a
match statement than patterns so it makes sense that this is the
default.
It would be a bit surprising if you are new to the `match` statement and
had not used something similar in another language, indeed. But how
often do people use `switch` with cases like this that don't use a
constant or literal value? It's not even supported in some popular
languages like C, and in the rare case that you need this behaviour, a
guard can be used:
match ($x) {
default if ($x === $y) => {
echo $y;
}
}
By the way, having one kinds of arm would mean you don't have to think
about the two kinds when reading code like this:
match ($x) {
$y => {
// …
},
let $y => {
// …
},
}
Also, imagine you want to equate multiple dynamic values with each other:
```
$x = ...;
$y = ...;
$z = ...;
match ($x) {
$y => ...,
$z => ...,
}
// If we only have pattern matching
match (true) {
true if $x === $y => ...,
true if $x === $z => ...,
}
```
True, that is less elegant. But when would you need to do that?
Thanks,
Andrea
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php