Hi Ilija,

śr., 25 mar 2020 o 13:10 Ilija Tovilo <ilija.tov...@me.com> napisał(a):

> Hi everybody!
>
>
>
> A few years ago I suggested adding a new `match` expression to the PHP
> language:
>
> https://externals.io/message/100487
>
>
>
> I arrogantly assumed someone will implement it for me which of course
> didn't happen. I'd finally like to get my own hands dirty. I have a very
> rough, incomplete prototype but I'd like to get your feedback before I
> continue working on the details.
>
>
>
> # Introduction
>
>
>
> This is what it looks like:
>
>
>
> ```php
>
> echo $i switch {
>
>     0 => "i equals 0",
>
>     1 => "i equals 1",
>
>     2 => "i equals 2",
>
>     3, 4 => "i equals 3 or 4",
>
> };
>
>
>
> // is roughly equivalent to
>
>
>
> switch ($i) {
>
>     case 0:
>
>         $tmp = "i equals 0";
>
>         break;
>
>     case 1:
>
>         $tmp = "i equals 1";
>
>         break;
>
>     case 2:
>
>         $tmp = "i equals 2";
>
>         break;
>
>     case 3:
>
>     case 4:
>
>         $tmp = "i equals 3 or 4";
>
>         break;
>
>     default:
>
>         throw new InvalidArgumentException('Unhandled switch case');
>
> }
>
>
>
> echo $tmp;
>
> ```
>
>
>
> Some things to note:
>
>
>
> * Each case only accepts a single expression
>
> * The entire switch expression evaluates to the result of the executed case
>
> * There is no fallthrough, an implicit break is added after every case
>
> * Multiple case conditions are possible with comma separation
>
> * The default case throws a InvalidArgumentException by default
>
> * The switch keyword is used as an infix operator
>
>
>
> # Syntax
>
>
>
> Originally, I expected to reuse the current syntax and transform it into
> an expression.
>
>
>
> ```php
>
> $x = switch ($y) { ... };
>
> ```
>
>
>
> Turns out this is ambiguous.
>
>
>
> ```php
>
> switch ($y) { ... }
>
> [$a] = ...;
>
>
>
> // Could also be interpreted as
>
> switch ($y) { ... }[$a] = ...;
>
> ```
>
>
>
> I stole the new syntax from C# 8.0 which means at least some people will
> already be familiar with it:
>
>
> https://docs.microsoft.com/en-us/archive/msdn-magazine/2019/may/csharp-8-0-pattern-matching-in-csharp-8-0#the-evolution-of-pattern-matching-in-c-80
>
>
>
> # Type coercion
>
>
>
> One of the bigger weak points of the `switch` statement is the fact that
> it performs implicit type coercion.
>
>
>
> ```php
>
> switch ('foo') {
>
>     case 0:
>
>         echo "Oh no!\n";
>
> }
>
> ```
>
>
>
> While it's very tempting to fix this in the new `switch` expression it
> adds a confusing discrepancy between the `switch` statement and expression.
> I think it would be preferrable to keep the two the same and change the
> behavior of both in a new PHP edition (
> https://github.com/php/php-rfcs/pull/2).
>
>
>
> # Pattern matching
>
>
>
> I decided against pattern matching because PHP doesn't have algebraic data
> types and classes rarely have public properties. In my opinion the limited
> use cases don't justify the significant complexity added to the language.
> It would also, once again, add an unjustified discrepancy between the
> `switch` statement and expression. If at some point we do want to introduce
> pattern matching it might be better to introduce a different keyword (e.g.
> `match`) and make it work for both the statement and expression. In case
> you need to match a more complex expression the following still works fine:
>
>
>
> ```php
>
> echo true switch {
>
>     is_int($x) => 'int',
>
>     is_float($x) => 'float',
>
>     is_string($x) => 'string',
>
>     ...
>
> };
>
> ```
>
>
>
> # Blocks
>
>
>
> Sometimes it would be useful to split the expression into multiple
> statements to make it more readable. Unfortunately, in PHP there are no
> block expressions. Rust allows returning the last value by omitting the
> semicolon:
>
>
>
> ```php
>
> echo $x switch {
>
>     1 => {
>
>         foo();
>
>         bar();
>
>         baz()
>
>     },
>
> };
>
> ```
>
>
>
> This is indeed possible in PHP and could be implemented as part of the
> `switch` expression or as a general language feature. A nice side effect is
> that this could also be used in arrow functions:
>
>
>
> ```php
>
> $x = fn() => {
>
>         foo();
>
>         bar();
>
>         baz()
>
> };
>
> ```
>
>
>
> This would, however, make it inconsistent with closures as they use the
> return keyword. Thus we would probably have to make sure arrow functions
> still work with return statement which would decrease the need for such a
> language construct. It is also very unlike anything else in PHP.
>
>
>
> # Poll
>
>
>
> This is a short overview of what I'll be working on in the coming weeks. I
> created a short poll for you guys to let me know if this idea is worth
> pursuing:
>
> https://forms.gle/stXMv72CAaDDxfwf8
>
>
>
> Stay safe!
>
>
That looks like what I've described a few months ago in
https://wiki.php.net/rfc/switch-expression-and-statement-improvement
If you dig into the mailing list you can even find almost ready to use
patch which implements it.

I'd love switch expression inclusion in PHP.

Cheers,
Michał Brzuchalski

Reply via email to