rfc:match_expression

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:match_expression [2020/04/24 19:40] – Finalize proposal ilijatovilorfc:match_expression [2020/05/09 15:59] (current) – Move to declined ilijatovilo
Line 2: Line 2:
   * Date: 2020-04-12   * Date: 2020-04-12
   * Author: Ilija Tovilo, tovilo.ilija@gmail.com   * Author: Ilija Tovilo, tovilo.ilija@gmail.com
-  * Status: Under Discussion+  * Status: Declined
   * Target Version: PHP 8.0   * Target Version: PHP 8.0
   * Implementation: https://github.com/php/php-src/pull/5371   * Implementation: https://github.com/php/php-src/pull/5371
Line 93: Line 93:
 <code php> <code php>
 switch ($pressedKey) { switch ($pressedKey) {
-    case Key::ENTER:+    case Key::RETURN_:
         save();         save();
         // Oops, forgot the break         // Oops, forgot the break
Line 212: Line 212:
 </code> </code>
  
-For the time being the following code will result in a compilation error:+For the time being using blocks in match expressions that use the return value in any way results in a compilation error:
  
 <code php> <code php>
Line 218: Line 218:
     0 => {},     0 => {},
 }; };
 +//> Match that is not used as a statement can't contain blocks
  
-//> Match that not used as a statement can't contain blocks+foo(match ($x) { 
 +    0 => {}, 
 +}); 
 +//> Match that is not used as a statement can't contain blocks 
 + 
 +1 + match ($x) { 
 +    0 => {}, 
 +}; 
 +//> Match that is not used as a statement can't contain blocks 
 + 
 +//etc. 
 + 
 +// Only allowed form 
 +match ($x) { 
 +    0 => {}, 
 +}
 </code> </code>
  
Line 245: Line 261:
 </code> </code>
  
-This introduces an ambiguity with the ''+'' and ''-'' prefix operators.+This introduces an ambiguity with the ''+'' and ''-'' unary operators.
  
 <code php> <code php>
Line 261: Line 277:
 </code> </code>
  
-When ''match'' appears as the first element of a statement would always be parsed as option 1 because there are no legitimate use cases for binary operations at a statement level. All other cases work as expected.+''match'' that appears as the first element of a statement would always be parsed as option 1 because there are no legitimate use cases for binary operations at a statement level. All other cases work as expected.
  
 <code php> <code php>
Line 267: Line 283:
 $x = match ($y) { ... } - 1; $x = match ($y) { ... } - 1;
 foo(match ($y) { ... } - 1); foo(match ($y) { ... } - 1);
-$x[] = fn() => match ($y) { ... };+$x[] = fn($y) => match ($y) { ... };
 // etc. // etc.
 +</code>
 +
 +This is also how Rust solves this ambiguity((https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=31b5bca165323726e7aa8d14f62f94d5)).
 +
 +<code rust>
 +match true { _ => () } - 1;
 +
 +// warning: unused unary operation that must be used
 +//  --> src/main.rs:2:28
 +//   |
 +// 2 |     match true { _ => () } - 1;
 +//                              ^^^
 +//   |
 </code> </code>
  
 Because there was some controversy around this feature it was moved to a secondary vote. Because there was some controversy around this feature it was moved to a secondary vote.
 +
 +===== Allow dropping (true) condition =====
 +It has been suggested to make no condition equivalent to ''(true)''.
 +
 +<code php>
 +match {
 +    $age >= 30 => {},
 +    $age >= 20 => {},
 +    $age >= 10 => {},
 +    default => {},
 +}
 +
 +// Equivalent to
 +
 +match (true) {
 +    $age >= 30 => {},
 +    $age >= 20 => {},
 +    $age >= 10 => {},
 +    default => {},
 +}
 +</code>
 +
 +The keyword ''match'' could be a bit misleading here. A potential gotcha is passing truthy values to the match which will not work as intended. But of course this issue remains regardless of dropping ''(true)'' or not.
 +
 +<code php>
 +match {
 +    preg_match(...) => {}, // preg_match returns 1 which is NOT identical (===) to true
 +}
 +</code>
 +
 +Because I have no strong opinion on this it will be moved to a secondary vote.
  
 ===== Miscellaneous ===== ===== Miscellaneous =====
 ==== Arbitrary expressions ==== ==== Arbitrary expressions ====
-A match condition can be any arbitrary expression. Analogous to ''switch'' each condition will be checked from top to bottom until the first one matches. If a condition matches the remaining conditions won't be evaluated+A match condition can be any arbitrary expression. Analogous to ''switch'' each condition will be checked from top to bottom until the first one matches. If a condition matches the remaining conditions won't be evaluated.
  
 <code php> <code php>
 match ($x) { match ($x) {
-    functionCall() => ..., +    foo() => ..., 
-    $this->methodCall() => ..., // methodCall isn't called if functionCall() matched with $x +    $this->bar() => ..., // bar() isn't called if foo() matched with $x 
-    $this->property => ...,+    $this->baz => ...,
     // etc.     // etc.
 } }
Line 377: Line 437:
  
     // Algebraic data types if we ever get them     // Algebraic data types if we ever get them
-    let Ast\BinaryExpr($lhs, '+', $rhs) => ...,+    let Ast::BinaryExpr($lhs, '+', $rhs) => ...,
 } }
  
Line 394: Line 454:
         && $value->getBar() === 2 => ..., // Object pattern         && $value->getBar() === 2 => ..., // Object pattern
     is_string($str) && $str !== '' => ..., // Guard     is_string($str) && $str !== '' => ..., // Guard
 +}
 +</code>
 +
 +==== Explicit fallthrough ====
 +Some people have suggested allowing explicit fallthrough to the next arm. This is, however, not a part of this RFC.
 +
 +<code php>
 +match ($x) {
 +    1 => {
 +        foo();
 +        fallthrough;
 +    },
 +    2 => {
 +        bar();
 +    },
 +}
 +
 +// 1 calls foo() and bar()
 +// 2 only calls bar()
 +</code>
 +
 +This would require a few sanity checks with pattern matching.
 +
 +<code php>
 +match ($x) {
 +    $a => { fallthrough; },
 +    $b => { /* $b is undefined */ },
 } }
 </code> </code>
Line 440: Line 527:
  
 Note that it will continue to work in method names and class constants. Note that it will continue to work in method names and class constants.
- 
-===== Proposed PHP Version(s) ===== 
-The proposed version is PHP 8. 
  
 ===== Proposed Voting Choices ===== ===== Proposed Voting Choices =====
-As this is a language change, a 2/3 majority is required. The vote is a straight Yes/No vote for accepting the RFC and merging the patch.+Voting starts 2020-04-25 and ends 2020-05-09.  
 + 
 +As this is a language change, a 2/3 majority is required.
  
 <doodle title="Would you like to add match expressions to the language?" auth="ilijatovilo" voteType="single" closed="true"> <doodle title="Would you like to add match expressions to the language?" auth="ilijatovilo" voteType="single" closed="true">
Line 459: Line 545:
 </doodle> </doodle>
  
-\\+Secondary vote (choice with the most votes is picked): 
 + 
 +<doodle title="Should we allow dropping (true) condition?" auth="ilijatovilo" voteType="single" closed="true"> 
 +   * Yes 
 +   * No 
 +</doodle> 
 + 
 +==== If you voted no, why? ==== 
 + 
 +  - Not interested 
 +  - I don't want blocks 
 +  - Missing return values in blocks 
 +  - Missing pattern matching 
 +  - Missing explicit fallthrough 
 +  - BC break is not acceptable 
 +  - Wanted [[https://wiki.php.net/rfc/switch_expression|switch expressions]] instead 
 +  - Other
  
 <doodle title="If you voted no, why?" auth="ilijatovilo" voteType="multi" closed="true"> <doodle title="If you voted no, why?" auth="ilijatovilo" voteType="multi" closed="true">
-   Not interested +   1 
-   Don't want blocks +   2 
-   Want return val in blocks +   3 
-   Not useful w/o pattern matching +   4 
-   BC break +   5 
-   Other+   
 +   * 7 
 +   * 8
 </doodle> </doodle>
  
rfc/match_expression.1587757255.txt.gz · Last modified: 2020/04/24 19:40 by ilijatovilo