rfc:throw_expression

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
rfc:throw_expression [2020/03/22 15:10]
ilijatovilo Add ternary example
rfc:throw_expression [2020/04/23 15:30] (current)
ilijatovilo Move to implemented
Line 1: Line 1:
 ====== PHP RFC: throw expression ====== ====== PHP RFC: throw expression ======
-  * Version: 0.9 
   * Date: 2020-03-21   * Date: 2020-03-21
-  * Author: Ilija Tovilo, ilija.tovilo@me.com+  * Author: Ilija Tovilo, tovilo.ilija@gmail.com
   * Target Version: PHP 8.0   * Target Version: PHP 8.0
-  * Status: Draft+  * Status: Implemented
   * Implementation: https://github.com/php/php-src/pull/5279   * Implementation: https://github.com/php/php-src/pull/5279
  
Line 14: Line 13:
  
 <code php> <code php>
-$callable = fn() => throw new Exception(); 
 // This was previously not possible since arrow functions only accept a single expression while throw was a statement. // This was previously not possible since arrow functions only accept a single expression while throw was a statement.
 +$callable = fn() => throw new Exception();
  
 +// $value is non-nullable.
 $value = $nullableValue ?? throw new InvalidArgumentException(); $value = $nullableValue ?? throw new InvalidArgumentException();
-// $value can now be considered non-nullable. 
  
 +// $value is truthy.
 $value = $falsableValue ?: throw new InvalidArgumentException(); $value = $falsableValue ?: throw new InvalidArgumentException();
-// $value can now be considered truthy. 
  
 +// $value is only set if the array is not empty.
 $value = !empty($array) $value = !empty($array)
     ? reset($array)     ? reset($array)
     : throw new InvalidArgumentException();     : throw new InvalidArgumentException();
-// $value is only set if the array is not empty. 
 </code> </code>
  
Line 32: Line 31:
  
 <code php> <code php>
 +// An if statement could make the intention clearer
 $condition && throw new Exception(); $condition && throw new Exception();
 $condition || throw new Exception(); $condition || throw new Exception();
 $condition and throw new Exception(); $condition and throw new Exception();
 $condition or throw new Exception(); $condition or throw new Exception();
-// An if statement could make the intention clearer 
 </code> </code>
  
 ===== Operator precedence ===== ===== Operator precedence =====
-If ''throw'' becomes an expression operator precedence becomes relevant. There are few operators that would even work in combination with the ''throw'' statement today. The ones that do are ''='', ''??='' and ''??''.+If ''throw'' becomes an expression operator precedence becomes relevant. These examples are working today.
  
 <code php> <code php>
-try { +throw $this->createNotFoundException(); 
-    throw $exception = new Exception('How useless'); +// Evaluated as 
-} catch (Exception $e) {} +throw ($this->createNotFoundException()); 
-echo $exception->getMessage(); +// Instead of 
-//> How useless+(throw $this)->createNotFoundException();
  
-try { +throw static::createNotFoundException(); 
-    $exception = null; +// Evaluated as 
-    throw $exception ??= new Exception('Still pretty useless'); +throw (static::createNotFoundException()); 
-} catch (Exception $e) {} +// Instead of 
-echo $exception->getMessage(); +(throw static)::createNotFoundException();
-//> Still pretty useless+
  
-try { +throw $userIsAuthorized ? new ForbiddenException() : new UnauthorizedException(); 
-    $exception = null; +// Evaluated as 
-    throw $exception ?? new Exception('Kind of useful'); +throw ($userIsAuthorized ? new ForbiddenException(: new UnauthorizedException()); 
-} catch (Exception $e+// Instead of 
-  echo $e->getMessage(); +(throw $userIsAuthorized) ? new ForbiddenException() : new UnauthorizedException();
-} +
-//> Kind of useful +
-</code>+
  
-While these cases are probably more rare it's important they continue working.+throw $maybeNullException ?? new Exception(); 
 +// Evaluated as 
 +throw ($maybeNullException ?? new Exception()); 
 +// Instead of 
 +(throw $maybeNullException) ?? new Exception();
  
-Although any binary operator can be used in the right-hand side of the ''throw'' statement none of them can evaluate to a ''Throwable'' value.+throw $exception = new Exception(); 
 +// Evaluated as 
 +throw ($exception = new Exception()); 
 +// Instead of 
 +(throw $exception) = new Exception();
  
-<code php> +throw $exception ??= new Exception(); 
-throw new Exception() + 1+// Evaluated as 
-//> Notice: Object of class Exception could not be converted to number in ... +throw ($exception ??= new Exception()); 
-//> Fatal error: Uncaught Error: Can only throw objects in ... +// Instead of 
-</code>+(throw $exception) ??= new Exception();
  
-This could change if the [[https://wiki.php.net/rfc/userspace_operator_overloading|RFCUserspace operator overloading]] gets accepted. There's already a [[https://github.com/php/pecl-php-operator|C extension]] that allows you to do the same thing.+throw $condition1 && $condition2 ? new Exception1() new Exception2(); 
 +// Evaluated as 
 +throw ($condition1 && $condition2 ? new Exception1() : new Exception2()); 
 +// Instead of 
 +(throw $condition1) && $condition2 ? new Exception1() new Exception2(); 
 +</code>
  
-For these reasons, this RFC proposes to use the lowest precedence for binary operators possible. This way all current code, even if broken, continues behaving the same way while also leaving the possibility of custom operators open in the future.+The common theme here is that everything after the ''throw'' keyword has a higher precedence. For this reason this RFC proposes to use the lowest operator precedence possible. All the current code, even if broken or strangewill continue behaving the same way. This isn't a problem because generally ''throw'' should be the last operator you're using as every expression after it wouldn't be evaluated anyway.
  
-One minor draw back is that the ''throw'' expression couldn't be used between two binary operators:+The only downside of the low precedence is that ''throw'' between two short-circuit operators would not be possible without parentheses:
  
 <code php> <code php>
Line 104: Line 112:
 Proposed version is PHP 8. Proposed version is PHP 8.
  
-===== RFC Impact ===== +===== Voting ===== 
-==== To SAPIs ==== +Voting starts 2020-04-05 and ends 2020-04-19
-None.+
  
-==== To Existing Extensions ==== +As this is a language change, a 2/3 majority is required. The vote is a straight Yes/No vote for accepting the RFC and merging the patch.
-None.+
  
-==== To Opcache ==== +<doodle title="Would you like to convert the throw statement into an expression?" auth="ilijatovilo" voteType="single" closed="true"> 
-None. +   * Yes 
- +   * No 
-===== Proposed Voting Choices ===== +</doodle>
-As this is a language change, a 2/3 majority is required. The vote is a straight Yes/No vote for accepting the RFC and merging the patch.+
  
 ===== References ===== ===== References =====
rfc/throw_expression.1584889803.txt.gz · Last modified: 2020/03/22 15:10 by ilijatovilo