Skip to content

[RFC] Switch expression #5308

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed

Conversation

iluuu1994
Copy link
Member

@iluuu1994 iluuu1994 commented Mar 27, 2020

Implementation for the coming switch expression RFC.

https://wiki.php.net/rfc/switch_expression

@iluuu1994 iluuu1994 force-pushed the switch-expression branch 2 times, most recently from 184a6e7 to 1b15392 Compare March 27, 2020 10:31
@ostrolucky
Copy link

Hello, can you explain what's difference between

return $x switch {
        0 => 'Zero',
        1 => 'One',
        2 => 'Two',
        3 => 'Three',
        4 => 'Four',
        5 => 'Five',
        6 => 'Six',
        7 => 'Seven',
        8 => 'Eight',
        9 => 'Nine',
    };

and

return [
        0 => 'Zero',
        1 => 'One',
        2 => 'Two',
        3 => 'Three',
        4 => 'Four',
        5 => 'Five',
        6 => 'Six',
        7 => 'Seven',
        8 => 'Eight',
        9 => 'Nine',
][$x];

? Because currently I don't see advantage of your proposal over simple array map.

@iluuu1994
Copy link
Member Author

iluuu1994 commented Mar 27, 2020

Your example will execute every arm.

return [
    0 => expensiveFunction1(),
    1 => expensiveFunction2(),
    ...
][$x];

Furthermore it builds a hash map in memory every time it executes. That is of course given the array isn't constant.

@ostrolucky
Copy link

Indeed. So it's more like

return [
        0 => fn() => 'Zero',
        1 => fn() => 'One',
        2 => fn() => 'Two',
        ...
][$x]();

@brzuchal
Copy link
Contributor

I prefer the return switch (expr) {}; form for three reasons:

  • it looks similar to switch statement we already have;
  • it doesn't look like the $x variable is gonna be populated with the result from switch expression;
  • it doesn't confuse like here print !true switch {}; where you have to think if ! has higher precedence or not.

I'm ok with losing the case keyword but am not sure if termination of a case by ; would be a better choice.
About the switch(true) expression, the simple return switch {}; I think could do the job and still be much readable. If there is a need for false switch expression then it can be put into parentheses - personally I think it would be a minor case.

@iluuu1994
Copy link
Member Author

@brzuchal

I prefer the return switch (expr) {}; form for three reasons:

I agree but as mentioned the syntax is ambiguous. Context-sensitive grammar has not been well accepted in PHP.

About the switch(true) expression, the simple return switch {};

That's a nice idea 🙂

@iluuu1994
Copy link
Member Author

@ostrolucky

Almost, you're still missing the default case.

It is in fact equivalent to:

switch ($x) {
    case 0:
        $tmp = 'Zero',
        break;
    case 1:
        $tmp = 'One',
        break;
    ...
    default:
        throw new InvalidArgumentException();
}

return $tmp;

It reuses the existing switch AST, code generation, opcodes, etc.

@@ -52,6 +52,7 @@ enum _zend_ast_kind {
ZEND_AST_STMT_LIST,
ZEND_AST_IF,
ZEND_AST_SWITCH_LIST,
ZEND_AST_SWITCH_CASE_COND_LIST,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could actually probably reuse the ZEND_AST_EXPR_LIST.

@iluuu1994
Copy link
Member Author

@webmozart I found a way to resolve the ambiguity after all. The only downside is that empty switch expressions are disallowed:

// This throws a parser error
$x => switch ($y) {};

@webmozart
Copy link

@iluuu1994 Nice! IMHO there's no valid use case for that, so I would expect a parser error to be thrown.

@@ -0,0 +1,23 @@
--TEST--
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is useless now.


?>
--EXPECTF--
Warning: assert(): assert('foo' switch {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This syntax needs to be updated.

@iluuu1994
Copy link
Member Author

Superseded by #5371.

@iluuu1994 iluuu1994 closed this Apr 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants