rfc:destructuring_coalesce

Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:destructuring_coalesce [2022/10/14 15:32] bwoebirfc:destructuring_coalesce [2022/11/26 15:07] (current) – updated status. danack
Line 3: Line 3:
   * Date: 2022-10-14   * Date: 2022-10-14
   * Author: Bob Weinand <bwoebi@php.net>   * Author: Bob Weinand <bwoebi@php.net>
-  * Status: Draft+  * Status: Declined
   * First Published at: http://wiki.php.net/rfc/destructuring_coalesce   * First Published at: http://wiki.php.net/rfc/destructuring_coalesce
  
Line 12: Line 12:
 ===== Proposal ===== ===== Proposal =====
  
-This RFC proposes the usage of the ''??'' coalescing operator in destructuring assignments, allowing for default values to be specified when an array key specified on the left-hand side does not exist in the destructured array.+This RFC proposes the usage of the ''??'' coalescing operator in destructuring assignments, allowing for default values to be specified when an array key specified on the left-hand side does not exist or is null in the destructured array.
  
 In its simplest form the destructuring coalesce will be written as follows: In its simplest form the destructuring coalesce will be written as follows:
Line 28: Line 28:
 </PHP> </PHP>
  
-Note that for nested destructuring, the coalescing does **not** skip the existence check of its container. Thus the following will emit an undefined key warning:+Also note that, equivalently to how ''??'' operates, the right-hand side is not evaluated at all, if the respective key exists and is not null in the source array. 
 + 
 +==== Use cases ==== 
 + 
 +Exploding an externally provided string, e.g. a key-value pair separated by ''='':
 <PHP> <PHP>
-[[$?? "default"]] = [];+$input = "key=value"; 
 +[$key, $val ?? null] = explode('=', $input, 2); 
 +// $key = "key", $val "value" 
 + 
 +$input = "onlykey"; 
 +[$key, $val ?? null= explode('=', $input, 2); 
 +// $key = "onlykey", $val = null, with no warning emitted
 </PHP> </PHP>
 +
 +Safely having default values on an externally provided json:
 +<PHP>
 +$json = '{"name":"Bob Weinand","locality":"Luxembourg"}';
 +list(
 +    "name" => $name ?? "unknown",
 +    "zipcode" => $zip ?? "not provided",
 +    "locality" => $locality ?? "World"
 +) = json_decode($json) ?: [];
 +// $name = "Bob Weinand", $zip = "not provided", $locality = "Luxembourg"
 +</PHP>
 +
 +Filling in ''null'' values on an array of data:
 +<PHP>
 +$data = [1, 2, null];
 +list($a, $b, $c ?? 3) = $data;
 +// $a = 1, $b = 2, $c = 3
 +</PHP>
 +
 +==== Semantics ====
 +
 +The semantics of list destructuring are generally preserved.
 +
 +An expression like
 +<PHP>
 +[[$a]] = $array;
 +</PHP>
 +is currently equivalent to (with ''$tmp'' denoting a temporary variable):
 +<PHP>
 +$tmp = $array;
 +$tmp = $tmp[0];
 +$a = $tmp[0];
 +</PHP>
 +
 +Thus an expression like
 +<PHP>
 +$array = [];
 +[[$a ?? "default"]] = $array; // the first [0] dimension does not exist
 +</PHP>
 +will be equivalent to:
 +<PHP>
 +$tmp = $array;
 +$tmp = $tmp[0]; // no coalesce here, emits an undefined key warning
 +$a = $tmp[0] ?? "default";
 +</PHP>
 +
 +Meaning that the existence of the container is always checked (producing undefined variable or key warnings if absent), only the the immediate entry which the coalesce operator is applied to never produces warnings if absent.
  
 It however is trivial to skip this check too, by defaulting the first nesting level to an empty array: It however is trivial to skip this check too, by defaulting the first nesting level to an empty array:
 <PHP> <PHP>
-[[$a ?? "default"] ?? []] = [];+[[$a ?? "default"] ?? []] = $array; 
 +// equivalent to: 
 +$tmp = $array; 
 +$tmp = $tmp[0?? []; 
 +$a = $tmp[0] ?? "default";
 </PHP> </PHP>
  
Line 41: Line 102:
 <PHP> <PHP>
 [$a ?? "default"] = $undefinedVariable; [$a ?? "default"] = $undefinedVariable;
-// Fix it via [$a ?? "default"] = $undefinedVariable ?? [];+// equivalent to: 
 +$tmp = $undefinedVariable; 
 +$a = $tmp[0] ?? "default"; 
 +</PHP> 
 + 
 +Which can be coalesced away with: 
 +<PHP> 
 +[$a ?? "default"] = $undefinedVariable ?? []
 +// equivalent to 
 +$tmp = $undefinedVariable ?? []; 
 +$a = $tmp[0] ?? "default";
 </PHP> </PHP>
  
Line 60: Line 131:
 With this proposal that issue does not exist and it is also not expected to be a major loss in ergonomics, as oftentimes, when you destructure, the base array is expected to exist. With this proposal that issue does not exist and it is also not expected to be a major loss in ergonomics, as oftentimes, when you destructure, the base array is expected to exist.
  
-It actually even allows one to concisely express nested array access with key checking, i.e., supposing we currently write code like ''$value = $array[0]["nested"][1] ?? "default";'', and we expect everything to exist, except possibly the last ''[1]'' dimension, it can be written as ''%%[["nested" => [1 => $value ?? "default"]]] = $array;%%'', checking for the existence of ''$array'', ''$array[0]'' and ''$array[0]["nested"]'' (and emitting warnings upon absence). The RFC author does not recommend writing code this way in general, but acknowledges that this is a possibility enabled by the outlined semantics.+It actually even allows one to concisely express nested array access with key checking, i.e., supposing we currently write code like 
 +<PHP> 
 +$value = $array[0]["nested"][1] ?? "default"; 
 +</PHP> 
 +and we expect everything to exist, except possibly the last ''[1]'' dimension, it can be written as follows: 
 +<PHP> 
 +[["nested" => [1 => $value ?? "default"]]] = $array; 
 +</PHP> 
 +checking for the existence of ''$array'', ''$array[0]'' and ''$array[0]["nested"]'' (and emitting warnings upon absence). The RFC author does not recommend writing code this way in general, but acknowledges that this is a possibility enabled by the outlined semantics.
  
-===== Proposed PHP Version(s) =====+==== Discussion of syntax ====
  
-Next minor version.+This RFC proposes using ''??'' as the default-operator for the simple fact that it actually does a coalescing operation. It is directly interpreted as a coalescing operation, with the same semantics: null and non existent keys are handled the same.
  
-===== Proposed Voting Choices =====+Other languages like Javascript have constructs like ''({ key: value = default } = object);'', with an equals sign before the default value. In particular, this matches the semantics Javascript also has for function parameter defaults: undefined and non-existent values are handled the same. So this makes sense in Javascript, but not in PHP. 
 + 
 +===== Proposed PHP Version(s) =====
  
-Add a destructuring coalesce feature as described?+PHP 8.3
  
-A 2/3 majority is required.+===== Compatibility =====
  
-===== Patches and Tests ===== +There's no BC break, not even a parser change, only not emitting a compiler error for coalesce in destructuring assignments.
-Links to any external patches and tests go here.+
  
-If there is no patch, make it clear who will create a patch, or whether a volunteer to help with implementation is needed.+===== Vote =====
  
-Make it clear if the patch is intended to be the final patch, or is just a prototype.+A 2/3 majority is required. The vote started 2022-11-07 and ended 2022-11-21.
  
-For changes affecting the core language, you should also provide patch for the language specification.+<doodle title="Add destructuring coalesce feature as described?" auth="bwoebi" voteType="single" closed="true"> 
 +   * Yes 
 +   * No 
 +</doodle>
  
 ===== Implementation ===== ===== Implementation =====
rfc/destructuring_coalesce.1665761539.txt.gz · Last modified: 2022/10/14 15:32 by bwoebi