On 09/09/2017 12:21, ilija.tov...@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]


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to