back

Bendegúz Csirmaz

This post is part of a series based on a presentation I gave at Cheppers on March 20, 2019.

PHP quiz #1 - for loop conditions

For loops are one of the most fundamental and ubiquitous control flow statements. They are so essential to day-to-day programming, you would expect every developer to know them inside out. As for me, I never would have thought I could learn anything new about them - I was wrong.

Question

What will this code output?

<?php

for ($i = 0, $j = 0; $i < 3, $j < 2; ++$i, ++$j) {
  echo "$i,$j\n";
}
  • A
    Syntax error
  • B
    0,0
    1,1
    2,2
  • C
    0,0
    1,1
  • D
    0,0
    1,1
    2,1

Answer

Show the answer
C
0,0
1,1

Explanation

It is perfectly legal to initialize and update multiple variables in for statements.

for ($i = 0, $j = 0; ...; ++$i, ++$j) // OK

This code does what you would expect: it introduces two variables, $i and $j with the initial value of 0, and increments them by one at the end of each iteration.

No trickery here.

The difficulty lies in the loop's condition instead.

for (...; $i < 3, $j < 2; ...) // ???

Although it might not be immediately obvious what effect does this code have on the loop, I can assure you, it is syntactically correct.

At first glance, it might seem like the loop defines multiple conditions that are ANDed or ORed together to decide when to terminate. This is a fair guess and it is not without reason. Haskell does something similar - it ANDs together multiple predicates in list comprehensions.

This is not the case here.

PHP has its roots in the C language. As such, it has a few weird historical remains that at first may sound completely counterintuitive.

$i < 3, $j < 2 is a single expression. Let's see what it evaluates to.

Comma operator (C)

In C, the comma operator (,) is an operator that evaluates two expressions and returns the result of the second one.

int a = (printf("Hello World!\n"), 1 + 2);

The above code prints Hello World! to the screen and assigns 3 to variable a. Both expressions are evaluated (printf gets called), but only the result of the second one is returned (which is 3).

Notice the parentheses around the expression in question. They are not mere ornaments. In C, the comma operator has the lowest precedence of all operators - that is to say, if we want to assign the result of a comma operator expression to a variable, we have to use parentheses.

Comma operator (PHP)

This ancient operator did not stand the test of time. Not many programming languages support it.

PHP does not do either. It is not listed in the precedence table and using it will generally result in a syntax error.

<?php

// Parse error: syntax error, unexpected ',' in ...
$a = (1, 2);

Surprisingly, there is an exception to the rule: for loop conditions.

For some strange reason, in for loop conditions the comma operator is correctly evaluated.

for (...; $i < 3, $j < 2; ...)
for (...; $j < 2; ...)

In this case, the expression $i < 3, $j < 2 has the same effect as $j < 2. The first operand is evaluated, but its result is disregarded.

The loop will only iterate twice.

Conclusion

PHP is an exceptional language. Literally: it has a lot of exceptions and weird rules, comma operators in for loop conditions being one of them.

Fortunately, there are not many great uses of this operator. It's just a curiosity.

In the next post we will continue looking at weird commas, but in a different context.

next >>