Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inconsistency in PHP documentation?

I am currently reading through the PHP specification here: https://github.com/php/php-langspec

  1. Now, I saw the list-intrinsic specification here, which states that for a list-intrinsic construct like below, the right-hand side of the simple-assignment-expression must be an expression that designates an array:

    list ( list-expression-listopt ) = expression

  2. But the documentation of list from php.net here, gives an example containing this:

    $result = $pdo->query("SELECT id, name, salary FROM employees");
    while (list($id, $name, $salary) = $result->fetch(PDO::FETCH_NUM)) {
        //output $id, $name and $salary
    }
    

The thing is that PDOStatement::fetch(PDO::FETCH_NUM) returns FALSE if there is no further row. But the right-hand side of the assignment-expression must be an array - and FALSE is not an array. So this would result in a fatal-error, right?

Have I missed something in the specification, or is this really an inconsistency?


According PHP bugreport
like image 460
MinecraftShamrock Avatar asked Feb 05 '15 12:02

MinecraftShamrock


1 Answers

This is deliberately done in the implementation of php to allow this dubious piece of code:

while (list($key, $value) = each($array)) {
  // ...
}

The result of each() may be false and would otherwise have triggered a nasty error, so while this behaviour is seemingly in violation with the specification it's mostly done to maintain backwards compatibility.

It's possible, though unlikely, that the next version of PHP will abolish this behaviour but at this point I would suggest that the specification could be edited to reflect this particular artefact, though the implied undefined behaviour could serve that purpose as well :)

Geeky details

The code for this can be found here; currently, the right-hand side expression supports:

  1. An array,
  2. An object that implements ArrayAccess,
  3. Something else.

In the case of "something else" it will just assign null to all the list variables.

Update

Nikita Popov has proposed the following specification update as part of a pull request:

list-intrinsic must be used as the left-hand operand in a simple-assignment-expression of which the right-hand operand must be an expression that designates an array or object implementing the ArrayAccess interface (called the source array).

...

This intrinsic assigns one or more elements of the source array to the 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.

(Changes emphasised)

like image 68
Ja͢ck Avatar answered Oct 19 '22 00:10

Ja͢ck