Hi Internals

I've just finished an implementation of 'switch-expression' that have been
discussed recently. So I would like to present my ideas here.

The basic syntax of switch-expression in this implementation is:

$result = switch ($expr) {
    case $cond1 => $result1,
    case $cond2 => $result2,
    case $cond3 => $result3,
    default => $default_result,
};

Like function declaration and function expression in JavaScript, if
`switch` appears as first token at statement level it will be recognized as
statement but if `switch` is in expression context it will be
switch-expression.

switch ($expr) {
    case $cond1 => $result1,
    case $cond2 => $result2,
    case $cond3 => $result3,
    default => $default_result,
};
// Parse error: syntax error, unexpected '=>' (T_DOUBLE_ARROW)

But this is OK.

!switch ($expr) {
    case $cond1 => $result1,
    case $cond2 => $result2,
    case $cond3 => $result3,
    default => $default_result,
}; // semicolon is still required because it is an expression

You can also use comma to associate multiple conditions with single result
expression.

$result = switch ($expr) {
    case $cond1 => $result1,
    case $cond2 => $result2,
    case $cond3, $cond4, $cond5 => $result3,
    default => $default_result,
};

Which is equivalent to:

$result = switch ($expr) {
    case $cond1 => $result1,
    case $cond2 => $result2,
    case $cond3 => $result3,
    case $cond4 => $result3,
    case $cond5 => $result3,
    default =>  $default_result,
};

If there's no default value or switch-expression will just give NULL.

$x = 'c';
$v = switch ($x) {
    case 'a' => 1,
    case 'b' => 2,
};
var_dump($v); // NULL

Empty switch-expression is also allowed.

$v = switch ($x) {
};
var_dump($v); // NULL

You can omit parenthesized expression which is shortcut to `switch (true)`.
This change applies to switch statement as well.

$v = switch {
    case $x >= 0 && $x <= 100 => 1,
    case $x >= 100 && $x <= 200 => 2,
    default => 3,
};

switch {
    case $x >= 0 && $x <= 100:
        doSomething1();
        break;
    case $x >= 100 && $x <= 200:
        doSomething2();
        break;
    default:
        doNothing();
        break;
}

You can also use `return` and `throw` in result expression. I recalled some
languages have this feature (but I've forgotten what language). This
feature can be very handy and useful in many use cases.

$x = 'd';
$v = switch ($x) {
    case 'a' => 1,
    case 'b' => 2,
    case 'c' => return true,
    default => throw new Exception("'$x' is not supported"),
};

Additional feature in the demo patch is the 'type guard' unary operator
which is an operator that will perform type check on given value and throw
`TypeError` when type mismatch occurred, otherwise return the value as is.
It has the same precedence  as `new`.

$a = 'This is a string';
$v = <int>$a; // TypeError: Value is expected to be int, string given

Just like type hints, can accept nullable types.

$v = <?int>switch ($x) {
    case 'a' => $result1,
    case 'b' => $result2,
};

Also works with variable references.

$x = &<int>$a;
$y = &<callable>$functions[$name];
$arr = [&<Countable>$obj];

This operator can also be used to simulate typed variables.

The demo is here:
https://github.com/webdevxp/php-src

P.S. This is just a bunch of ideas with concrete demo, not intended to be
pull request nor proposal because I think I'm still new here and
inexperienced in many other ways.

Cheers

Reply via email to