Skip to content

Commit 37c8bb5

Browse files
Allow specifying keys on list() elements
Squashed commit of the following: commit 0361dbe Author: Andrea Faulds <[email protected]> Date: Fri Mar 25 16:59:20 2016 +0000 UPGRADING and NEWS commit dca9d4a Author: Andrea Faulds <[email protected]> Date: Fri Mar 25 16:45:18 2016 +0000 Add tests contributed by @jesseschalken commit e557f77 Author: Andrea Faulds <[email protected]> Date: Fri Mar 25 16:44:51 2016 +0000 Rebuild VM commit 70942e4 Author: Andrea Faulds <[email protected]> Date: Wed Feb 24 13:12:26 2016 +0000 Add test for evaluation order of nested list() keys commit ed3592e Author: Andrea Faulds <[email protected]> Date: Wed Feb 24 12:42:04 2016 +0000 Add test for evaluation order commit 589756c Author: Andrea Faulds <[email protected]> Date: Tue Jan 19 17:29:34 2016 +0000 Allow arbitrary expressions for key commit 3f62207 Author: Andrea Faulds <[email protected]> Date: Tue Jan 19 17:45:10 2016 +0000 Remove compile-time HANDLE_NUMERIC (see bug #63217) commit bab7581 Author: Andrea Faulds <[email protected]> Date: Sun Jan 17 01:20:26 2016 +0000 Handle numeric strings commit 14bfe93 Author: Andrea Faulds <[email protected]> Date: Sun Jan 17 01:09:36 2016 +0000 Allow trailing comma commit f4c8b2c Author: Andrea Faulds <[email protected]> Date: Sat Jan 16 23:47:11 2016 +0000 Add tests commit 0085884 Author: Andrea Faulds <[email protected]> Date: Sat Jan 16 22:24:23 2016 +0000 Handle non-integer/string opcodes commit e572d2d Author: Andrea Faulds <[email protected]> Date: Sat Jan 16 21:10:33 2016 +0000 Disallow mixing keyed and unkeyed list() elements commit cede13c Author: Andrea Faulds <[email protected]> Date: Sun Jan 10 20:46:44 2016 +0000 list() with keys (no foreach or tests)
1 parent 0e5fa32 commit 37c8bb5

21 files changed

+1484
-45
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ PHP NEWS
1212
. Added void return type. (Andrea)
1313
. Added support for negative string offsets in string offset syntax and
1414
various string functions. (Francois)
15+
. Added a form of the list() construct where keys can be specified. (Andrea)
1516

1617
- FTP:
1718
. Implemented FR #55651 (Option to ignore the returned FTP PASV address).

UPGRADING

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ PHP 7.1 UPGRADE NOTES
3535
. String offset access now supports negative references, which will be
3636
counted from the end of the string.
3737
(RFC: https://wiki.php.net/rfc/negative-string-offsets)
38+
. Added a form of the list() construct where keys can be specified.
39+
(RFC: https://wiki.php.net/rfc/list_keys)
3840

3941
========================================
4042
3. Changes in SAPI modules

Zend/tests/foreach_list_keyed.phpt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
foreach with list syntax, keyed
3+
--FILE--
4+
<?php
5+
6+
$points = [
7+
["x" => 1, "y" => 2],
8+
["x" => 2, "y" => 1]
9+
];
10+
11+
foreach ($points as list("x" => $x, "y" => $y)) {
12+
var_dump($x, $y);
13+
}
14+
15+
echo PHP_EOL;
16+
17+
$invertedPoints = [
18+
"x" => [1, 2],
19+
"y" => [2, 1]
20+
];
21+
22+
foreach ($invertedPoints as list(0 => $row1, 1 => $row2)) {
23+
var_dump($row1, $row2);
24+
}
25+
26+
?>
27+
--EXPECT--
28+
int(1)
29+
int(2)
30+
int(2)
31+
int(1)
32+
33+
int(1)
34+
int(2)
35+
int(2)
36+
int(1)

Zend/tests/list_keyed.phpt

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
--TEST--
2+
list() with keys
3+
--FILE--
4+
<?php
5+
6+
$antonyms = [
7+
"good" => "bad",
8+
"happy" => "sad",
9+
];
10+
11+
list("good" => $good_antonym, "happy" => $happy_antonym) = $antonyms;
12+
var_dump($good_antonym, $happy_antonym);
13+
14+
echo PHP_EOL;
15+
16+
$powersOfTwo = [
17+
1 => 2,
18+
2 => 4,
19+
3 => 8
20+
];
21+
22+
list(1 => $two_1, 2 => $two_2, 3 => $two_3) = $powersOfTwo;
23+
var_dump($two_1, $two_2, $two_3);
24+
25+
echo PHP_EOL;
26+
27+
$contrivedMixedKeyTypesExample = [
28+
7 => "the best PHP version",
29+
"elePHPant" => "the cutest mascot"
30+
];
31+
32+
list(7 => $seven, "elePHPant" => $elePHPant) = $contrivedMixedKeyTypesExample;
33+
var_dump($seven, $elePHPant);
34+
35+
echo PHP_EOL;
36+
37+
$allTogetherNow = [
38+
"antonyms" => $antonyms,
39+
"powersOfTwo" => $powersOfTwo,
40+
"contrivedMixedKeyTypesExample" => $contrivedMixedKeyTypesExample
41+
];
42+
43+
list(
44+
"antonyms" => list("good" => $good_antonym, "happy" => $happy_antonym),
45+
"powersOfTwo" => list(1 => $two_1, 2 => $two_2, 3 => $two_3),
46+
"contrivedMixedKeyTypesExample" => list(7 => $seven, "elePHPant" => $elePHPant)
47+
) = $allTogetherNow;
48+
49+
var_dump($good_antonym, $happy_antonym);
50+
var_dump($two_1, $two_2, $two_3);
51+
var_dump($seven, $elePHPant);
52+
53+
?>
54+
--EXPECT--
55+
string(3) "bad"
56+
string(3) "sad"
57+
58+
int(2)
59+
int(4)
60+
int(8)
61+
62+
string(20) "the best PHP version"
63+
string(17) "the cutest mascot"
64+
65+
string(3) "bad"
66+
string(3) "sad"
67+
int(2)
68+
int(4)
69+
int(8)
70+
string(20) "the best PHP version"
71+
string(17) "the cutest mascot"
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
--TEST--
2+
list() with keys and ArrayAccess
3+
--FILE--
4+
<?php
5+
6+
$antonymObject = new ArrayObject;
7+
$antonymObject["good"] = "bad";
8+
$antonymObject["happy"] = "sad";
9+
10+
list("good" => $good, "happy" => $happy) = $antonymObject;
11+
var_dump($good, $happy);
12+
13+
echo PHP_EOL;
14+
15+
$stdClassCollection = new SplObjectStorage;
16+
$foo = new StdClass;
17+
$stdClassCollection[$foo] = "foo";
18+
$bar = new StdClass;
19+
$stdClassCollection[$bar] = "bar";
20+
21+
list($foo => $fooStr, $bar => $barStr) = $stdClassCollection;
22+
var_dump($fooStr, $barStr);
23+
24+
echo PHP_EOL;
25+
26+
class IndexPrinter implements ArrayAccess
27+
{
28+
public function offsetGet($offset) {
29+
echo "GET ";
30+
var_dump($offset);
31+
}
32+
public function offsetSet($offset, $value) {
33+
}
34+
public function offsetExists($offset) {
35+
}
36+
public function offsetUnset($offset) {
37+
}
38+
}
39+
40+
$op = new IndexPrinter;
41+
list(123 => $x) = $op;
42+
// PHP shouldn't convert this to an integer offset, because it's ArrayAccess
43+
list("123" => $x) = $op;
44+
45+
?>
46+
--EXPECT--
47+
string(3) "bad"
48+
string(3) "sad"
49+
50+
string(3) "foo"
51+
string(3) "bar"
52+
53+
GET int(123)
54+
GET string(3) "123"
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
list() with non-integer-or-string keys
3+
--FILE--
4+
<?php
5+
6+
$results = [
7+
0 => 0,
8+
1 => 1,
9+
"" => ""
10+
];
11+
12+
list(NULL => $NULL, 1.5 => $float, FALSE => $FALSE, TRUE => $TRUE) = $results;
13+
var_dump($NULL, $float, $FALSE, $TRUE);
14+
15+
echo PHP_EOL;
16+
17+
list("0" => $zeroString, "1" => $oneString) = $results;
18+
var_dump($zeroString, $oneString);
19+
20+
list(STDIN => $resource) = [];
21+
22+
?>
23+
--EXPECTF--
24+
string(0) ""
25+
int(1)
26+
int(0)
27+
int(1)
28+
29+
int(0)
30+
int(1)
31+
32+
Notice: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php declare(strict_types=1);
2+
3+
// Observer objects for the Zend/tests/list_keyed_evaluation_order.* tests
4+
5+
class Stringable
6+
{
7+
private $name;
8+
public function __construct(string $name) {
9+
$this->name = $name;
10+
}
11+
12+
public function __toString(): string {
13+
echo "$this->name evaluated.", PHP_EOL;
14+
return $this->name;
15+
}
16+
}
17+
18+
class Indexable implements ArrayAccess
19+
{
20+
private $array;
21+
public function __construct(array $array) {
22+
$this->array = $array;
23+
}
24+
25+
public function offsetExists($offset): bool {
26+
echo "Existence of offset $offset checked for.", PHP_EOL;
27+
return isset($this->array[$offset]);
28+
}
29+
30+
public function offsetUnset($offset): void {
31+
unset($this->array[$offset]);
32+
echo "Offset $offset removed.", PHP_EOL;
33+
}
34+
35+
public function offsetGet($offset) {
36+
echo "Offset $offset retrieved.", PHP_EOL;
37+
return $this->array[$offset];
38+
}
39+
40+
public function offsetSet($offset, $value): void {
41+
$this->array[$offset] = $value;
42+
echo "Offset $offset set to $value.", PHP_EOL;
43+
}
44+
}
45+
46+
class IndexableRetrievable
47+
{
48+
private $label;
49+
private $indexable;
50+
51+
public function __construct(string $label, Indexable $indexable) {
52+
$this->label = $label;
53+
$this->indexable = $indexable;
54+
}
55+
56+
public function getIndexable(): Indexable {
57+
echo "Indexable $this->label retrieved.", PHP_EOL;
58+
return $this->indexable;
59+
}
60+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
list() with keys, evaluation order
3+
--FILE--
4+
<?php
5+
6+
require_once "list_keyed_evaluation_order.inc";
7+
8+
$a = new Stringable("A");
9+
$c = new Stringable("C");
10+
11+
$e = new IndexableRetrievable("E", new Indexable(["A" => "value for offset A", "C" => "value for offset C"]));
12+
13+
$store = new Indexable([]);
14+
15+
// list($a => $b, $c => $d) = $e;
16+
// Should be evaluated in the order:
17+
// 1. Evaluate $e
18+
// 2. Evaluate $a
19+
// 3. Evaluate $e[$a]
20+
// 4. Assign $b from $e[$a]
21+
// 5. Evaluate $c
22+
// 6. Evaluate $e[$c]
23+
// 7. Assign $c from $e[$a]
24+
25+
list((string)$a => $store["B"], (string)$c => $store["D"]) = $e->getIndexable();
26+
27+
?>
28+
--EXPECT--
29+
Indexable E retrieved.
30+
A evaluated.
31+
Offset A retrieved.
32+
Offset B set to value for offset A.
33+
C evaluated.
34+
Offset C retrieved.
35+
Offset D set to value for offset C.
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
--TEST--
2+
list() with keys, evaluation order #2
3+
--FILE--
4+
<?php
5+
6+
// All the following should print 'a' then 'b'
7+
8+
list($a, $b) = ['a', 'b'];
9+
var_dump($a);
10+
var_dump($b);
11+
12+
list(0 => $a, 1 => $b) = ['a', 'b'];
13+
var_dump($a);
14+
var_dump($b);
15+
16+
list(1 => $b, 0 => $a) = ['a', 'b'];
17+
var_dump($a);
18+
var_dump($b);
19+
20+
$arr = [];
21+
list($arr[], $arr[]) = ['a', 'b'];
22+
var_dump($arr[0]);
23+
var_dump($arr[1]);
24+
25+
$arr = [];
26+
list(0 => $arr[], 1 => $arr[]) = ['a', 'b'];
27+
var_dump($arr[0]);
28+
var_dump($arr[1]);
29+
30+
$arr = [];
31+
list(1 => $arr[], 0 => $arr[]) = ['b', 'a'];
32+
var_dump($arr[0]);
33+
var_dump($arr[1]);
34+
35+
$arr = [];
36+
list(list(1 => $arr[], 0 => $arr[])) = [['b', 'a']];
37+
var_dump($arr[0]);
38+
var_dump($arr[1]);
39+
40+
$arr = [];
41+
list('key1' => $arr[], 'key2' => $arr[]) = ['key2' => 'b', 'key1' => 'a'];
42+
var_dump($arr[0]);
43+
var_dump($arr[1]);
44+
45+
// This should print 'foo'
46+
$a = 0;
47+
list($a => $a) = ['foo', 'bar'];
48+
var_dump($a);
49+
50+
// This should print 'bar' then 'foo'
51+
$a = 0;
52+
$b = 1;
53+
list($b => $a, $a => $c) = ['bar' => 'foo', 1 => 'bar'];
54+
var_dump($a);
55+
var_dump($c);
56+
57+
?>
58+
--EXPECT--
59+
string(1) "a"
60+
string(1) "b"
61+
string(1) "a"
62+
string(1) "b"
63+
string(1) "a"
64+
string(1) "b"
65+
string(1) "a"
66+
string(1) "b"
67+
string(1) "a"
68+
string(1) "b"
69+
string(1) "a"
70+
string(1) "b"
71+
string(1) "a"
72+
string(1) "b"
73+
string(1) "a"
74+
string(1) "b"
75+
string(3) "foo"
76+
string(3) "bar"
77+
string(3) "foo"

0 commit comments

Comments
 (0)