Permalink
Browse files

Allow specifying keys on list() elements

Squashed commit of the following:

commit c56f6e3
Author: Andrea Faulds <[email protected]>
Date:   Wed Feb 24 13:49:17 2016 +0000

    Import Zend Engine tests for list()

commit 3afd58a
Author: Andrea Faulds <[email protected]>
Date:   Wed Feb 24 13:49:05 2016 +0000

    Update specification for list() keys
  • Loading branch information...
1 parent 2888f58 commit 0b1a497a6c847f6566f32057f55259f68bb9ce38 @TazeTSchnitzel TazeTSchnitzel committed Mar 25, 2016
@@ -414,9 +414,17 @@ isset($v1, $v2, $v3); // results in FALSE
list ( <i>list-expression-list<sub>opt</sub></i> )
<i>list-expression-list:</i>
+ <i>unkeyed-list-expression-list</i>
+ <i>keyed-list-expression-list</i> ,<sub>opt</sub>
+
+ <i>unkeyed-list-expression-list:</i>
<i>list-or-variable</i>
,
- <i>list-expression-list</i> , <i>list-or-variable<sub>opt</sub></i>
+ <i>unkeyed-list-expression-list</i> , <i>list-or-variable<sub>opt</sub></ii>
+
+ <i>keyed-list-expression-list:</i>
+ <i>expression</i> => <i>list-or-variable</i>
+ <i>keyed-list-expression-list</i> , <i>expression</i> => <i>list-or-variable</i>
<i>list-or-variable:</i>
<i>list-intrinsic</i>
@@ -446,7 +454,8 @@ target variables. On success, it returns a copy of the source array. If the
source array is not an array or object implementing `ArrayAccess` no
assignments are performed and the return value is `NULL`.
-All elements in the source array having keys of type `string` are ignored.
+For *unkeyed-list-expression-list*, all elements in the source array having
+keys of type `string` are ignored.
The element having an `int` key of 0 is assigned to the first target
variable, the element having an `int` key of 1 is assigned to the second
target variable, and so on, until all target variables have been
@@ -455,6 +464,15 @@ fewer source array elements having int keys than there are target
variables, the unassigned target variables are set to `NULL` and
a non-fatal error is produced.
+For *keyed-list-expression-list*, each key-variable pair is handled in turn,
+with the key and variable being separated by the `=>` symbol.
+The element having the first key, with the key having been converted using the
+same rules as the [subscript operator](10-expressions.md#subscript-operator),
+is assigned to the frst target variable. This process is repeated for the
+second `=>` pair, if any, and so on. Any other array elements are ignored.
+If there is no array element with a given key, the unassigned target variable
+is set to `NULL` and a non-fatal error is produced.
+
The assignments must occur in this order.
Any target variable may be a list, in which case, the corresponding
@@ -481,6 +499,24 @@ list($arr[1], $arr[0]) = [0, 1];
// $arr is [1 => 0, 0 => 1], in this order
list($arr2[], $arr2[]) = [0, 1];
// $arr2 is [0, 1]
+
+list("one" => $one, "two" => $two) = ["one" => 1, "two" => 2];
+ // $one is 1, $two is 2
+list(
+ "one" => $one,
+ "two" => $two,
+) = [
+ "one" => 1,
+ "two" => 2,
+];
+ // $one is 1, $two is 2
+list(list("x" => $x1, "y" => $y1), list("x" => $x2, "y" => $y2)) = [
+ ["x" => 1, "y" => 2],
+ ["x" => 3, "y" => 4]
+];
+ // $x1 is 1, $y1 is 2, $x2 is 3, $y2 is 4
+list(0 => list($x1, $x2), 1 => list($x2, $y2)) = [[1, 2], [3, 4]];
+ // $x1 is 1, $y1 is 2, $x2 is 3, $y2 is 4
```
####print
View
@@ -426,9 +426,17 @@ The grammar notation is described in [Grammars section](09-lexical-structure.md#
list ( <i>list-expression-list<sub>opt</sub></i> )
<i>list-expression-list:</i>
+ <i>unkeyed-list-expression-list</i>
+ <i>keyed-list-expression-list</i> ,<sub>opt</sub>
+
+ <i>unkeyed-list-expression-list:</i>
<i>list-or-variable</i>
,
- <i>list-expression-list</i> , <i>list-or-variable<sub>opt</sub></i>
+ <i>unkeyed-list-expression-list</i> , <i>list-or-variable<sub>opt</sub></i>
+
+ <i>keyed-list-expression-list:</i>
+ <i>expression</i> => <i>list-or-variable</i>
+ <i>keyed-list-expression-list</i> , <i>expression</i> => <i>list-or-variable</i>
<i>list-or-variable:</i>
<i>list-intrinsic</i>
@@ -0,0 +1,14 @@
+--TEST--
+"Nested" list()
+--FILE--
+<?php
+
+list($a, list($b)) = array(new stdclass, array(new stdclass));
+var_dump($a, $b);
+
+?>
+--EXPECT--
+object(stdClass)#1 (0) {
+}
+object(stdClass)#2 (0) {
+}
@@ -0,0 +1,20 @@
+--TEST--
+Testing full-reference on list()
+--FILE--
+<?php
+
+error_reporting(E_ALL);
+
+$a = new stdclass;
+$b =& $a;
+
+list($a, list($b)) = array($a, array($b));
+var_dump($a, $b, $a === $b);
+
+?>
+--EXPECT--
+object(stdClass)#1 (0) {
+}
+object(stdClass)#1 (0) {
+}
+bool(true)
@@ -0,0 +1,24 @@
+--TEST--
+list() with non-array
+--FILE--
+<?php
+
+list($a) = NULL;
+
+list($b) = 1;
+
+list($c) = 1.;
+
+list($d) = 'foo';
+
+list($e) = print '';
+
+var_dump($a, $b, $c, $d, $e);
+
+?>
+--EXPECT--
+NULL
+NULL
+NULL
+NULL
+NULL
@@ -0,0 +1,21 @@
+--TEST--
+list() with array reference
+--FILE--
+<?php
+
+$arr = array(2, 1);
+$b =& $arr;
+
+list(,$a) = $b;
+
+var_dump($a, $b);
+
+?>
+--EXPECT--
+int(1)
+array(2) {
+ [0]=>
+ int(2)
+ [1]=>
+ int(1)
+}
@@ -0,0 +1,50 @@
+--TEST--
+Testing list() with several variables
+--FILE--
+<?php
+
+$str = "foo";
+
+list($a, $b, $c) = $str;
+
+var_dump($a, $b, $c);
+
+print "----\n";
+
+$int = 1;
+
+list($a, $b, $c) = $int;
+
+var_dump($a, $b, $c);
+
+print "----\n";
+
+$obj = new stdClass;
+
+list($a, $b, $c) = $obj;
+
+var_dump($a, $b, $c);
+
+print "----\n";
+
+$arr = array(1, 2, 3);
+
+list($a, $b, $c) = $arr;
+
+var_dump($a, $b, $c);
+
+?>
+--EXPECTF--
+NULL
+NULL
+NULL
+----
+NULL
+NULL
+NULL
+----
+
+Fatal error: Uncaught Error: Cannot use object of type stdClass as array in %s:%d
+Stack trace:
+#0 {main}
+ thrown in %s on line %d
@@ -0,0 +1,12 @@
+--TEST--
+Testing nested list() with empty array
+--FILE--
+<?php
+
+list($a, list($b, list(list($d)))) = array();
+
+?>
+--EXPECTF--
+Notice: Undefined offset: 0 in %s on line %d
+
+Notice: Undefined offset: 1 in %s on line %d
@@ -0,0 +1,15 @@
+--TEST--
+Using lambda with list()
+--FILE--
+<?php
+
+list($x, $y) = function() { };
+
+var_dump($x, $y);
+
+?>
+--EXPECTF--
+Fatal error: Uncaught Error: Cannot use object of type Closure as array in %slist_007.php:3
+Stack trace:
+#0 {main}
+ thrown in %slist_007.php on line 3
@@ -0,0 +1,49 @@
+--TEST--
+list() can be used to destructure to string offsets, __set and ArrayAccess::offsetSet
+--FILE--
+<?php
+
+class Obj {
+ public $values = [];
+ public function __set($name, $value) {
+ $this->values[$name] = $value;
+ }
+}
+
+class Arr implements ArrayAccess {
+ public $values = [];
+ public function offsetSet($name, $value) {
+ $this->values[$name] = $value;
+ }
+ public function offsetGet($name) {}
+ public function offsetExists($name) {}
+ public function offsetUnset($name) {}
+}
+
+$str = 'ab';
+list($str[0], $str[1]) = ['x', 'y'];
+var_dump($str);
+
+$obj = new Obj;
+list($obj->foo, $obj->bar) = ['foo', 'bar'];
+var_dump($obj->values);
+
+$arr = new Arr;
+list($arr['foo'], $arr['bar']) = ['foo', 'bar'];
+var_dump($arr->values);
+
+?>
+--EXPECT--
+string(2) "xy"
+array(2) {
+ ["foo"]=>
+ string(3) "foo"
+ ["bar"]=>
+ string(3) "bar"
+}
+array(2) {
+ ["foo"]=>
+ string(3) "foo"
+ ["bar"]=>
+ string(3) "bar"
+}
@@ -0,0 +1,10 @@
+--TEST--
+Empty list() assignments are not allowed
+--FILE--
+<?php
+
+list(,,,,,,,,,,) = [];
+
+?>
+--EXPECTF--
+Fatal error: Cannot use empty list in %s on line %d
@@ -0,0 +1,71 @@
+--TEST--
+list() with keys
+--FILE--
+<?php
+
+$antonyms = [
+ "good" => "bad",
+ "happy" => "sad",
+];
+
+list("good" => $good_antonym, "happy" => $happy_antonym) = $antonyms;
+var_dump($good_antonym, $happy_antonym);
+
+echo PHP_EOL;
+
+$powersOfTwo = [
+ 1 => 2,
+ 2 => 4,
+ 3 => 8
+];
+
+list(1 => $two_1, 2 => $two_2, 3 => $two_3) = $powersOfTwo;
+var_dump($two_1, $two_2, $two_3);
+
+echo PHP_EOL;
+
+$contrivedMixedKeyTypesExample = [
+ 7 => "the best PHP version",
+ "elePHPant" => "the cutest mascot"
+];
+
+list(7 => $seven, "elePHPant" => $elePHPant) = $contrivedMixedKeyTypesExample;
+var_dump($seven, $elePHPant);
+
+echo PHP_EOL;
+
+$allTogetherNow = [
+ "antonyms" => $antonyms,
+ "powersOfTwo" => $powersOfTwo,
+ "contrivedMixedKeyTypesExample" => $contrivedMixedKeyTypesExample
+];
+
+list(
+ "antonyms" => list("good" => $good_antonym, "happy" => $happy_antonym),
+ "powersOfTwo" => list(1 => $two_1, 2 => $two_2, 3 => $two_3),
+ "contrivedMixedKeyTypesExample" => list(7 => $seven, "elePHPant" => $elePHPant)
+) = $allTogetherNow;
+
+var_dump($good_antonym, $happy_antonym);
+var_dump($two_1, $two_2, $two_3);
+var_dump($seven, $elePHPant);
+
+?>
+--EXPECT--
+string(3) "bad"
+string(3) "sad"
+
+int(2)
+int(4)
+int(8)
+
+string(20) "the best PHP version"
+string(17) "the cutest mascot"
+
+string(3) "bad"
+string(3) "sad"
+int(2)
+int(4)
+int(8)
+string(20) "the best PHP version"
+string(17) "the cutest mascot"
Oops, something went wrong.

0 comments on commit 0b1a497

Please sign in to comment.