Re: [RFC] Match expression

From: 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]

« previous php.internals (#100502) next »