Hi Kosit,
There's some really interesting ideas in here, thanks for sharing them.
On 19/10/2019 17:40, Kosit Supanyo wrote:
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
This feels like an odd restriction to me, and one that as far as I'm
aware PHP doesn't have anywhere else. For instance, it might be
considered bad style, but it's possible to use a ternary operator as an
abbreviated if statement:
isset($_GET['logout']) ? $session->logout() : $session->extend();
Was this restriction added to make the implementation easier, or because
you thought it was a useful feature?
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;
}
This is an interesting idea, given that switch(true) is the documented
way to do this right now. However, I've always felt switch(true) was
rather limited in its advantage over if-elseif. I would prefer a syntax
that reduced the boilerplate for:
* Different comparisons applied to the same variable/expression, e.g.
match($user->getScore()) { case <0 => foo(), case >100 => bar(), default
=> baz() }
* Different values compared against the same expression using the same
operator, e.g. match( $exception instanceOf ) { case FooException =>
handleFoo(), case BarException => handleBar() }
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"),
};
This seems confusing to me, because it mixes statements and expressions
in a rather unusual way. The "return" case in particular seems ambiguous
- if $v is visible outside the function, will it have a value assigned
to it by the "return" branch, and if so what would that value be? I can
imagine more use cases for the "throw" version, and it's reasonably
obvious how it would behave, so it might be reasonable to have that one
special case.
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
This is a very interesting feature, although I think what would be even
more useful would be syntax to check if something _can_ be cast, i.e.
the same check you have here, but as an operator evaluating to boolean.
That way, you could write code like this:
if ( <int>$_GET['id'] ) {
$user = getUser($_GET['id']):
}
else {
echo "Invalid ID provided";
}
Which would be equivalent (given a type hint on getUser() and no
strict_types declaration) to this, but without needing to use exceptions
as flow control:
try {
getUser($_GET['id']);
}
catch ( TypeError $e ) {
echo "Invalid ID provided";
}
Regards,
--
Rowan Tommins (né Collins)
[IMSoP]
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php