Re: [RFC] Match expression
| From: | Rowan Collins | Date: | Sun, 10 Sep 2017 14:43:18 +0000 |
| Subject: | Re: [RFC] Match expression | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-100502@lists.php.net to get a copy of this message | ||
On 09/09/2017 12:21, ilija.tovilo@me.com wrote:
Hi everybody! Has this idea been discussed before? I find myself writing switch statements in PHP quite rarely. This has a few reasons: 1. It doesn’t have a "strict_types” version 2. It is quite verbose (lots of breaks) 3. It is a statement rather than an expression Often, if / elseif statements turn out to be shorter, safer and easier to read than the switch statement.I've had the idea kicking around my head for some time of a "switch-use" statement. I keep hoping to find the time to play around with the PHP parser and see if I can write a proof of concept implementation, just as an excuse to get deeper into the source, but since this has come up, I'll outline the idea. The general form would be "switch ( expression ) use ( op ) { ... }", where "op" is any binary operator which gives a boolean result, and the rest looks the same as a normal PHP switch statement. The simplest example would be to do a strict comparison by using "===": switch ( someFunction() ) use ( === ) { case 42:
// ...break; case '42':
// ...break; } Which would approximately de-sugar to: $temp = someFunction(); switch ( true ) { case $temp === 42:
// ...break; case $temp === '42':
// ...break; } As you can see, the switch(true) version has to use an explicit variable to avoid re-computing the expression, which switch does for you, and you then have to repeat the "$temp ===", obscuring the fact that all cases are checking the same thing. A normal switch, however, can't distinguish 42 from '42', because it uses the == comparison rules. If this were the only useful operator, we might just call it "switch strict" or something, but here are a couple of examples with other operators: // Generic exception handling function // Also useful when accepting various incompatible implementations of something and wrapping or converting them switch ( $e ) use ( instanceof ) { case FooException: case BarException:
// ...break; case SomeOtherException:
// ...break; } // Dividing a circle into arbitrary sectors, based on this Stack Overflow question: https://stackoverflow.com/q/44183771/157957 // Note the ability to place "default" at the top, rather than duplicating code in an else clause switch ( $angle ) use ( <= ) { case 30: default:
return Direction::Right;break; case 60:
return Direction::UP_RIGHT;break; case 120:
return Direction::UP;break; case 150:
return Direction::UP_LEFT;break; case 210:
return Direction::LEFT;break; case 240:
return Direction::DOWN_LEFT;break; case 300:
return Direction::DOWN;break; case 330:
return Direction::DOWN_RIGHT;break; } There are a couple of ways to expand this further, if we wanted: * Allow operators whose result isn't strictly a boolean, such as bitwise & * Allow any 2-parameter callable in place of an operator, to have more complex comparisons. With Andrea's "operator functions" suggestion, operators would technically just be a subset of this anyway. The below would be quite useful, but unfortunately preg_match takes ($pattern, $subject) and this would need ($subject, $pattern), so you'd need some extra transform: switch ( $message ) use ( 'preg_match' ) { case '/^Missing parameter:/': case '/^Unexpected parameter:/':
return self::MALFORMED_REQUEST;break; case '/.*try again later.$/':
return self::TEMPORARY_ERROR;break; } Any thoughts? Regards, -- Rowan Collins [IMSoP]