Hi everybody!

 

A few years ago I suggested adding a new `match` expression to the PHP language:

https://externals.io/message/100487

 

I arrogantly assumed someone will implement it for me which of course didn't 
happen. I'd finally like to get my own hands dirty. I have a very rough, 
incomplete prototype but I'd like to get your feedback before I continue 
working on the details.

 

# Introduction

 

This is what it looks like:

 

```php

echo $i switch {

    0 => "i equals 0",

    1 => "i equals 1",

    2 => "i equals 2",

    3, 4 => "i equals 3 or 4",

};

 

// is roughly equivalent to

 

switch ($i) {

    case 0:

        $tmp = "i equals 0";

        break;

    case 1:

        $tmp = "i equals 1";

        break;

    case 2:

        $tmp = "i equals 2";

        break;

    case 3:

    case 4:

        $tmp = "i equals 3 or 4";

        break;

    default:

        throw new InvalidArgumentException('Unhandled switch case');

}

 

echo $tmp;

```

 

Some things to note:

 

* Each case only accepts a single expression

* The entire switch expression evaluates to the result of the executed case

* There is no fallthrough, an implicit break is added after every case

* Multiple case conditions are possible with comma separation

* The default case throws a InvalidArgumentException by default

* The switch keyword is used as an infix operator

 

# Syntax

 

Originally, I expected to reuse the current syntax and transform it into an 
expression.

 

```php

$x = switch ($y) { ... };

```

 

Turns out this is ambiguous.

 

```php

switch ($y) { ... }

[$a] = ...;

 

// Could also be interpreted as

switch ($y) { ... }[$a] = ...;

```

 

I stole the new syntax from C# 8.0 which means at least some people will 
already be familiar with it:

https://docs.microsoft.com/en-us/archive/msdn-magazine/2019/may/csharp-8-0-pattern-matching-in-csharp-8-0#the-evolution-of-pattern-matching-in-c-80

 

# Type coercion

 

One of the bigger weak points of the `switch` statement is the fact that it 
performs implicit type coercion.

 

```php

switch ('foo') {

    case 0:

        echo "Oh no!\n";

}

```

 

While it's very tempting to fix this in the new `switch` expression it adds a 
confusing discrepancy between the `switch` statement and expression. I think it 
would be preferrable to keep the two the same and change the behavior of both 
in a new PHP edition (https://github.com/php/php-rfcs/pull/2).

 

# Pattern matching

 

I decided against pattern matching because PHP doesn't have algebraic data 
types and classes rarely have public properties. In my opinion the limited use 
cases don't justify the significant complexity added to the language. It would 
also, once again, add an unjustified discrepancy between the `switch` statement 
and expression. If at some point we do want to introduce pattern matching it 
might be better to introduce a different keyword (e.g. `match`) and make it 
work for both the statement and expression. In case you need to match a more 
complex expression the following still works fine:

 

```php

echo true switch {

    is_int($x) => 'int',

    is_float($x) => 'float',

    is_string($x) => 'string',

    ...

};

```

 

# Blocks

 

Sometimes it would be useful to split the expression into multiple statements 
to make it more readable. Unfortunately, in PHP there are no block expressions. 
Rust allows returning the last value by omitting the semicolon:

 

```php

echo $x switch {

    1 => {

        foo();

        bar();

        baz()

    },

};

```

 

This is indeed possible in PHP and could be implemented as part of the `switch` 
expression or as a general language feature. A nice side effect is that this 
could also be used in arrow functions:

 

```php

$x = fn() => {

        foo();

        bar();

        baz()

};

```

 

This would, however, make it inconsistent with closures as they use the return 
keyword. Thus we would probably have to make sure arrow functions still work 
with return statement which would decrease the need for such a language 
construct. It is also very unlike anything else in PHP.

 

# Poll

 

This is a short overview of what I'll be working on in the coming weeks. I 
created a short poll for you guys to let me know if this idea is worth pursuing:

https://forms.gle/stXMv72CAaDDxfwf8

 

Stay safe!

 

Reply via email to