Ka=Ping Yee’s Equality Test
Here’s a quickie PHP script based on the one that appears in Ka-Ping Yee’s LiveJournal entry titled Why PHP Should Never Be Taught:
<?php
$a = 0;
$b = "eggs";
$c = "spam";
$e = "eggs";
echo "<h1>The \"==\" Exercise</h1>";
echo "<ul>";
echo "<li>\$a is $a</li>";
echo "<li>\$b is $b</li>";
echo "<li>\$c is $c</li>";
echo "<li>\$d is undefined</li>";
echo "<li>\$e is $e</li>";
echo "</ul>";
echo ($a == $b) ? "\$a == \$b<br />" : "\$a != \$b<br />";
echo ($b == $c) ? "\$b == \$c<br />" : "\$b != \$c<br />";
echo ($a == $c) ? "\$a == \$c<br />" : "\$a != \$c<br />";
echo ($a == $d) ? "\$a == \$d<br />" : "\$a != \$d<br />";
echo ($b == $d) ? "\$b == \$d<br />" : "\$b != \$d<br />";
echo ($c == $d) ? "\$c == \$d<br />" : "\$c != \$d<br />";
echo ($b == $e) ? "\$b == \$e<br />" : "\$b != \$e<br />";
?>
If you’re not familiar with PHP’s quirks, you’ll find the output surprising:
The “==” Exercise
- $a is 0
- $b is eggs
- $c is spam
- $d is undefined
- $e is eggs
$a == $b
$b != $c
$a == $c
$a == $d
$b != $d
$c != $d
$b == $e
What Happened?
In PHP, as with many other programming languages, the ==
operator is the equality operator, which returns true
if the operands on either side are equal in value. It works as expected when used on operands of the same type, as evidenced by the program above, which states that $b
is equal in value to $e
, both of which are set to the string eggs
.
We get into strange territory when the ==
operator is used to compare operands of different types. The program above evaluates the boolean $a == $b
as true
even though $a
is set to the integer value 0
and $b
is set to the value eggs
. How can eggs
be equivalent to 0
? They’re so tasty and versatile! Damned anti-ovites!
In PHP, the ==
operator is what I like to call the “Slack Equality Operator”. When used to compare a string and a number, it attempts to convert the string to a numeric type and then performs the comparison. The following example code, taken from the PHP documentation, shows how PHP’s string-to-number coercion works:
<?php
$foo = 1 + "10.5"; // $foo is float (11.5)
$foo = 1 + "-1.3e3"; // $foo is float (-1299)
$foo = 1 + "bob-1.3e3"; // $foo is integer (1)
$foo = 1 + "bob3"; // $foo is integer (1)
$foo = 1 + "10 Small Pigs"; // $foo is integer (11)
$foo = 4 + "10.2 Little Piggies"; // $foo is float (14.2)
$foo = "10.0 pigs " + 1; // $foo is float (11)
$foo = "10.0 pigs " + 1.0; // $foo is float (11)
?>
Hence the eggs/zero equivalence: the string eggs
is coerced to 0
.
Enter the ===
Operator
I like to call the ===
the “Strict Equality Operator”. It returns true
if and only if:
- Both operands are the same type
- Both operands have the same value
Here’s the code I showed at the start of the article, but with all instances of ==
replaced with ===
:
<?php
$a = 0;
$b = "eggs";
$c = "spam";
$e = "eggs";
echo "<h1>The \"===\" Exercise</h1>";
echo "<ul>";
echo "<li>\$a is $a</li>";
echo "<li>\$b is $b</li>";
echo "<li>\$c is $c</li>";
echo "<li>\$d is undefined</li>";
echo "<li>\$e is $e</li>";
echo "</ul>";
echo ($a === $b) ? "\$a === \$b<br />" : "\$a != \$b<br />";
echo ($b === $c) ? "\$b === \$c<br />" : "\$b != \$c<br />";
echo ($a === $c) ? "\$a === \$c<br />" : "\$a != \$c<br />";
echo ($a === $d) ? "\$a === \$d<br />" : "\$a != \$d<br />";
echo ($b === $d) ? "\$b === \$d<br />" : "\$b != \$d<br />";
echo ($c === $d) ? "\$c === \$d<br />" : "\$c != \$d<br />";
echo ($b === $e) ? "\$b === \$e<br />" : "\$b != \$e<br />";
?>
Here’s the output, which behaves as expected:
The “===” Exercise
- $a is 0
- $b is eggs
- $c is spam
- $d is undefined
- $e is eggs
$a != $b
$b != $c
$a != $c
$a != $d
$b != $d
$c != $d
$b === $e
Once More, in Ruby
Just for kicks, I thought I’d translate the original code into Ruby just to see what would happen. Here’s the code:
a = 0
b = "eggs"
c = "spam"
e = "eggs"
puts "a is 0"
puts "b is 'eggs'"
puts "c is 'spam'"
puts "e is 'eggs'"
puts a == b ? "a == b" : "a != b"
puts b == c ? "b == c" : "b != c"
puts a == c ? "a == c" : "a != c"
puts a == d ? "a == d" : "a != d"
puts b == d ? "b == d" : "b != d"
puts c == d ? "c == d" : "c != d"
puts b == e ? "b == e" : "b != e"
…and here’s the output:
a is 0
b is 'eggs'
c is 'spam'
e is 'eggs'
a != b
b != c
a != c
double-equals.rb:14: undefined local variable or method `d' for main:Object (NameError)
Links
- Zestyping’s LiveJournal: Why PHP Should Never Be Taught
- PHP Manual: PHP Type Comparison Tables
- Well House Consultants: Assignment, Equality and Identity in PHP
- JonLee.ca: The Triple Equals in PHP
One reply on “In PHP, There’s Equality, and Then There’s EQUALITY”
[…] In PHP, There’s Equality, and Then There’s EQUALITY By Joey deVilla In PHP, the == operator is what I like to call the “Slack Equality Operator”. When used to compare a string and a number, it attempts to convert the string to a numeric type and then performs the comparison. The following example code, … Global Nerdy – http://globalnerdy.com […]