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

Reply via email to