Skip to content

Commit 0b1a497

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
1 parent 2888f58 commit 0b1a497

25 files changed

+888
-3
lines changed

spec/10-expressions.md

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,9 +414,17 @@ isset($v1, $v2, $v3); // results in FALSE
414414
list ( <i>list-expression-list<sub>opt</sub></i> )
415415

416416
<i>list-expression-list:</i>
417+
<i>unkeyed-list-expression-list</i>
418+
<i>keyed-list-expression-list</i> ,<sub>opt</sub>
419+
420+
<i>unkeyed-list-expression-list:</i>
417421
<i>list-or-variable</i>
418422
,
419-
<i>list-expression-list</i> , <i>list-or-variable<sub>opt</sub></i>
423+
<i>unkeyed-list-expression-list</i> , <i>list-or-variable<sub>opt</sub></ii>
424+
425+
<i>keyed-list-expression-list:</i>
426+
<i>expression</i> => <i>list-or-variable</i>
427+
<i>keyed-list-expression-list</i> , <i>expression</i> => <i>list-or-variable</i>
420428

421429
<i>list-or-variable:</i>
422430
<i>list-intrinsic</i>
@@ -446,7 +454,8 @@ target variables. On success, it returns a copy of the source array. If the
446454
source array is not an array or object implementing `ArrayAccess` no
447455
assignments are performed and the return value is `NULL`.
448456

449-
All elements in the source array having keys of type `string` are ignored.
457+
For *unkeyed-list-expression-list*, all elements in the source array having
458+
keys of type `string` are ignored.
450459
The element having an `int` key of 0 is assigned to the first target
451460
variable, the element having an `int` key of 1 is assigned to the second
452461
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
455464
variables, the unassigned target variables are set to `NULL` and
456465
a non-fatal error is produced.
457466

467+
For *keyed-list-expression-list*, each key-variable pair is handled in turn,
468+
with the key and variable being separated by the `=>` symbol.
469+
The element having the first key, with the key having been converted using the
470+
same rules as the [subscript operator](10-expressions.md#subscript-operator),
471+
is assigned to the frst target variable. This process is repeated for the
472+
second `=>` pair, if any, and so on. Any other array elements are ignored.
473+
If there is no array element with a given key, the unassigned target variable
474+
is set to `NULL` and a non-fatal error is produced.
475+
458476
The assignments must occur in this order.
459477

460478
Any target variable may be a list, in which case, the corresponding
@@ -481,6 +499,24 @@ list($arr[1], $arr[0]) = [0, 1];
481499
// $arr is [1 => 0, 0 => 1], in this order
482500
list($arr2[], $arr2[]) = [0, 1];
483501
// $arr2 is [0, 1]
502+
503+
list("one" => $one, "two" => $two) = ["one" => 1, "two" => 2];
504+
// $one is 1, $two is 2
505+
list(
506+
"one" => $one,
507+
"two" => $two,
508+
) = [
509+
"one" => 1,
510+
"two" => 2,
511+
];
512+
// $one is 1, $two is 2
513+
list(list("x" => $x1, "y" => $y1), list("x" => $x2, "y" => $y2)) = [
514+
["x" => 1, "y" => 2],
515+
["x" => 3, "y" => 4]
516+
];
517+
// $x1 is 1, $y1 is 2, $x2 is 3, $y2 is 4
518+
list(0 => list($x1, $x2), 1 => list($x2, $y2)) = [[1, 2], [3, 4]];
519+
// $x1 is 1, $y1 is 2, $x2 is 3, $y2 is 4
484520
```
485521

486522
####print

spec/19-grammar.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,9 +426,17 @@ The grammar notation is described in [Grammars section](09-lexical-structure.md#
426426
list ( <i>list-expression-list<sub>opt</sub></i> )
427427

428428
<i>list-expression-list:</i>
429+
<i>unkeyed-list-expression-list</i>
430+
<i>keyed-list-expression-list</i> ,<sub>opt</sub>
431+
432+
<i>unkeyed-list-expression-list:</i>
429433
<i>list-or-variable</i>
430434
,
431-
<i>list-expression-list</i> , <i>list-or-variable<sub>opt</sub></i>
435+
<i>unkeyed-list-expression-list</i> , <i>list-or-variable<sub>opt</sub></i>
436+
437+
<i>keyed-list-expression-list:</i>
438+
<i>expression</i> => <i>list-or-variable</i>
439+
<i>keyed-list-expression-list</i> , <i>expression</i> => <i>list-or-variable</i>
432440

433441
<i>list-or-variable:</i>
434442
<i>list-intrinsic</i>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
"Nested" list()
3+
--FILE--
4+
<?php
5+
6+
list($a, list($b)) = array(new stdclass, array(new stdclass));
7+
var_dump($a, $b);
8+
9+
?>
10+
--EXPECT--
11+
object(stdClass)#1 (0) {
12+
}
13+
object(stdClass)#2 (0) {
14+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Testing full-reference on list()
3+
--FILE--
4+
<?php
5+
6+
error_reporting(E_ALL);
7+
8+
$a = new stdclass;
9+
$b =& $a;
10+
11+
list($a, list($b)) = array($a, array($b));
12+
var_dump($a, $b, $a === $b);
13+
14+
?>
15+
--EXPECT--
16+
object(stdClass)#1 (0) {
17+
}
18+
object(stdClass)#1 (0) {
19+
}
20+
bool(true)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
list() with non-array
3+
--FILE--
4+
<?php
5+
6+
list($a) = NULL;
7+
8+
list($b) = 1;
9+
10+
list($c) = 1.;
11+
12+
list($d) = 'foo';
13+
14+
list($e) = print '';
15+
16+
var_dump($a, $b, $c, $d, $e);
17+
18+
?>
19+
--EXPECT--
20+
NULL
21+
NULL
22+
NULL
23+
NULL
24+
NULL
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
list() with array reference
3+
--FILE--
4+
<?php
5+
6+
$arr = array(2, 1);
7+
$b =& $arr;
8+
9+
list(,$a) = $b;
10+
11+
var_dump($a, $b);
12+
13+
?>
14+
--EXPECT--
15+
int(1)
16+
array(2) {
17+
[0]=>
18+
int(2)
19+
[1]=>
20+
int(1)
21+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
--TEST--
2+
Testing list() with several variables
3+
--FILE--
4+
<?php
5+
6+
$str = "foo";
7+
8+
list($a, $b, $c) = $str;
9+
10+
var_dump($a, $b, $c);
11+
12+
print "----\n";
13+
14+
$int = 1;
15+
16+
list($a, $b, $c) = $int;
17+
18+
var_dump($a, $b, $c);
19+
20+
print "----\n";
21+
22+
$obj = new stdClass;
23+
24+
list($a, $b, $c) = $obj;
25+
26+
var_dump($a, $b, $c);
27+
28+
print "----\n";
29+
30+
$arr = array(1, 2, 3);
31+
32+
list($a, $b, $c) = $arr;
33+
34+
var_dump($a, $b, $c);
35+
36+
?>
37+
--EXPECTF--
38+
NULL
39+
NULL
40+
NULL
41+
----
42+
NULL
43+
NULL
44+
NULL
45+
----
46+
47+
Fatal error: Uncaught Error: Cannot use object of type stdClass as array in %s:%d
48+
Stack trace:
49+
#0 {main}
50+
thrown in %s on line %d
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
Testing nested list() with empty array
3+
--FILE--
4+
<?php
5+
6+
list($a, list($b, list(list($d)))) = array();
7+
8+
?>
9+
--EXPECTF--
10+
Notice: Undefined offset: 0 in %s on line %d
11+
12+
Notice: Undefined offset: 1 in %s on line %d
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
Using lambda with list()
3+
--FILE--
4+
<?php
5+
6+
list($x, $y) = function() { };
7+
8+
var_dump($x, $y);
9+
10+
?>
11+
--EXPECTF--
12+
Fatal error: Uncaught Error: Cannot use object of type Closure as array in %slist_007.php:3
13+
Stack trace:
14+
#0 {main}
15+
thrown in %slist_007.php on line 3
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
--TEST--
2+
list() can be used to destructure to string offsets, __set and ArrayAccess::offsetSet
3+
--FILE--
4+
<?php
5+
6+
class Obj {
7+
public $values = [];
8+
public function __set($name, $value) {
9+
$this->values[$name] = $value;
10+
}
11+
}
12+
13+
class Arr implements ArrayAccess {
14+
public $values = [];
15+
public function offsetSet($name, $value) {
16+
$this->values[$name] = $value;
17+
}
18+
public function offsetGet($name) {}
19+
public function offsetExists($name) {}
20+
public function offsetUnset($name) {}
21+
}
22+
23+
$str = 'ab';
24+
list($str[0], $str[1]) = ['x', 'y'];
25+
var_dump($str);
26+
27+
$obj = new Obj;
28+
list($obj->foo, $obj->bar) = ['foo', 'bar'];
29+
var_dump($obj->values);
30+
31+
$arr = new Arr;
32+
list($arr['foo'], $arr['bar']) = ['foo', 'bar'];
33+
var_dump($arr->values);
34+
35+
?>
36+
--EXPECT--
37+
string(2) "xy"
38+
array(2) {
39+
["foo"]=>
40+
string(3) "foo"
41+
["bar"]=>
42+
string(3) "bar"
43+
}
44+
array(2) {
45+
["foo"]=>
46+
string(3) "foo"
47+
["bar"]=>
48+
string(3) "bar"
49+
}

0 commit comments

Comments
 (0)