How useful is the new ?: operator?

As with everyone else excited about PHP 5.3, I was extremely looking forward to developing in it. I was especially excited to use the new shorthand ternary operator (?:). This would remove the redundant middle expression of returning the variable, and instead would return itself if it evaluated to true. But after much testing and trying to implement it in interesting ways, the shorthand ternary just isn't as useful as you would hope. The primary problem is the left-most expression must evaluate to true or false, which isn't possible with the shorthand. Below is my test case.

error_reporting(E_ALL | E_STRICT);

class Ternary {
	private $__data = array('key' => 'value');

	public function get($key, $default = null) {
		return $this->__data[$key] ?: $default;
	}
}

$test = new Ternary();

var_dump($test->get('key')); echo '<br>';
var_dump($test->get('test')); echo '<br>';
var_dump($test->get('')); echo '<br>';
var_dump($test->get(false)); echo '<br>';
var_dump($test->get(null)); echo '<br>';

This test works for the most part, the value or null is always returned. However, the problem is that this technique throws notice errors; here is the result after running the test. You can easily avoid this by turning of notice errors, but that's bad practice.

string(5) "value"

Notice: Undefined index: test in C:\xampp\htdocs\scripts\index.php on line 9
NULL

Notice: Undefined index: in C:\xampp\htdocs\scripts\index.php on line 9
NULL

Notice: Undefined offset: 0 in C:\xampp\htdocs\scripts\index.php on line 9
NULL

Notice: Undefined index: in C:\xampp\htdocs\scripts\index.php on line 9
NULL

I was hoping the new shorthand ternary would internally run an isset() and evaluate automatically, but it looks like it does not. So now we are still stuck with the old verbose way of doing things.

return isset($this->__data[$key]) ? $this->__data[$key] : $default;

Is there a reason why the PHP devs chose not to run an isset automatically? Or am I doing something wrong here? More information on this would be helpful, because I believe the operator would be multitudes more useful if it worked like I suggested.

Using Closures as callbacks within loops

In jQuery (and other Javascript frameworks) it is quite common to use closures (I refer to them as callback functions) to loop over arrays or objects. Even though it's a slow process and is much more efficient to use the built-in for loop, it got me thinking. Why not try and use the new Closure class in PHP 5.3 and see how well it performs within a loop? Suffice to say, I got some really really interesting results. Before I get into the details, here is the test script I wrote (the Benchmark class is merely a class I have written in the past).

<?php $data = range(0, 1000);
$clean = array();

public function loop($array, Closure $closure) {
	if (!empty($array)) {
		foreach ($array as $key => $value) {
			$closure($key, $value);
		}
	}
}

Benchmark::start('loop');

foreach ($data as $key => $value) {
	$clean[$key] = $value;
}

loop($data, function($key, $value) {
	$clean[$key] = $value;
});

Benchmark::stop('loop');
echo Benchmark::display('loop'); ?>

I didn't get too in depth with my test cases and simply used Firefox and page refresh to get my results. I am running PHP 5.3.1 on a Windows 7 XAMPP installation with Apache and no caching. For benchmarking I was using microtime(true) and memory_get_usage().

I began testing with 4 different cases, each of which that changed the size of the $data array. I started with 1000 iterations, then 5000, then 10000 and lastly 100000. I would comment out the foreach/loop sections and run them one at a time (of course), and ran each test about 5 times to gather an average. Here are the results.

foreach:
1000	Time: 0.0010 / Memory: 137128 (Max: 689160)
5000	Time: 0.0052 / Memory: 706488 (Max: 1258528)
10000	Time: 0.0097 / Memory: 1412048 (Max: 1964120)
100000	Time: 0.0545 / Memory: 13849568 (Max: 14401656)

closure:
1000	Time: 0.0027 / Memory: 84984 (Max: 688832)
5000	Time: 0.0144 / Memory: 433672 (Max: 1258192)
10000	Time: 0.0267 / Memory: 866448 (Max: 1963744)
100000	Time: 0.1223 / Memory: 8525216 (Max: 14401256)

The first thing you will notice is the time it took to interpret the page. On average using a closure as a callback within a loop will take 2-3x longer to process. However, the interesting thing is that the memory usage is around 40% smaller (using more allocated memory) while using a closure than doing a foreach, yet the max allocated is nearly identical. I knew what the outcome would be before I even started it -- Javascript closures are the same way. Regardless it was a fun experiment and if anyone knows more about this, please shed some light on this topic for the rest of us!

But in closing I can sadly say, that no, you should not be using a closure for looping, just stick to the old fashion tried and true foreach or for loop.