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