Archive for May, 2008

PHP’s create_function() and closures

Posted on May 17th, 2008 in Code, JavaScript, PHP | No Comments »

A coworker recently asked me what the difference was, functionally, between PHP’s create_function() function and traditional closures that you might find in languages with first-class functions, like Ruby or JavaScript. You can pretty easily illustrate this with a couple of examples.

First, a bit about closures. The idea with closures is that you can cleanly and readably pass around a bit of logic as an object, and any references that that object makes to variables in the surrounding scope must persist until that object is done with them.

So here’s an example in JavaScript:

<script type="text/javascript">
function getGreeter(name)
{
    return function(salutation) {
        alert(salutation + ', ' + name);
    }
}

var greeter = getGreeter('Eddy');
greeter('Hello');   // Hello, Eddy
greeter('Howdy');   // Howdy, Eddy
greeter('Bonjour'); // Bonjour, Eddy
</script>

Here’s the closest equivalent in PHP:

<?php
$code = '$name, $salutation', 'print $salutation . ', ' . $name;';
$greeter = create_function($code);
$greeter('Eddy', 'Hello');
// etc.

And that’s a callback, not a closure. In JavaScript the garbage collector reclaims the memory used by the anonymous “greeter” function… but in PHP functions get declared and stay declared, so every time you call create_function(), you increase the memory usage.

It gets worse. This is basically what PHP does internally:

<?php
function create_function($args, $code)
{
    // create a random $functionName
    eval('function ' . $functionName . '($args){$code}');
    return $functionName;
}

Yeah, the entire thing is evaluated. So not only does it not get garbage collected, but it has all the problems of eval()—it’s slow, difficult to debug, and uncacheable by bytecode caches like APC. Problems that closures don’t have in other languages.

It’s why you can do something like this…

<?php
$code = 'print "I print repeatedly.\n"; } print "I print once.\n"; if (false) {';
$function = create_function('', $code);
call_user_func($function);
call_user_func($function);
call_user_func($function);

// I print once.
// I print repeatedly.
// I print repeatedly.
// I print repeatedly.

…and why you should never use create_function().

Converting string literals in PHP

Posted on May 17th, 2008 in Code, PHP | No Comments »

In PHP (and most languages), this is false:

'\143\141\164' == "\143\141\164"

No surprise there. One is a 12-byte string of backslashes and numbers, and the other is a 3-byte string of octal values spelling “cat”. When you use double quotes, PHP transparently converts the string.

Sometimes it’s convenient to write values in files as string literals that represent characters. Some values simply don’t translate well in their native form, and it’s more explicit to write them out “long hand” in octal or hexadecimal. This is useful if you have to match, say, an exotic series of characters with 100% accuracy.

But what happens when you need to clue PHP in that the string “\143\141\164″ (as read from a file) should equal “cat”? As far as I know, there’s no easy way to do this. Presumably, there should be a function—something like str_convert_literals()—which would accept a string and do the conversion itself. But there isn’t, so you must rely on regular expressions.

Here’s the solution I found after some trying various other methods (like tokenizing the string):

$string = preg_replace_callback('/\\\\([0-7]{1,3})/', 'convertOctalToCharacter',
                                $string);

function convertOctalToCharacter($octal)
{
    return chr(octdec($octal[1]));
}

I’ll run through what’s going on briefly. The regular expression matches anything following a backslash that is a series of up to three digits, 0-7 (octal is base 8, after all). It passes that match to the convertOctalToCharacter() function, which converts the value to decimal and then feeds it to the chr() function (which only accepts decimal values). That in turn converts the integer to its corresponding character value, which is then substituted into the string.

Based on this, the hexadecimal conversion function isn’t very difficult to guess. To get you started, I’ll give you a not-so-subtle hint: the regular expression is “/\\\\x([0-9A-F]{1,2})/i”.

One more thing: if you also translate special characters like “\r”, consider using lookbehinds in your expression to ensure that valid sequences like \\r aren’t converted twice.

Color Picker for OS X

Posted on May 5th, 2008 in Mac OS X | 2 Comments »

This morning I needed to choose a hex color, but I didn’t have easy access to the Color Picker utility in Mac OS X. So I spent about 15 minutes creating a Color Picker.app utility and installed some plugins. Yes, you can install plugins for Color Picker.

Color Picker on the dock

Download Color Picker.app here.

Just drag to /Applications/Utilities/ and then you can find the Color Picker in Spotlight.

While you’re at it, make Color Picker more useful by installing these plugins: