Perl vs PHP

Some quick notes on PHP equivalents to Perl constructs like map, grep etc to ease with changing between the two languages.

grep vs array_filter()

Perl's grep function is very useful for processing a list and returning items which match a given expression.

Example:

# look through a hash for keys where the value is > 5
my @keys = grep { $hash{$_} > 5 } keys %hash;
 
# just look for some matches:
my @matches = grep /foo/ @things;

PHP doesn't have anything quite as efficient, but similar results can be had by using array_filter with a callback function:

$array = array(foo => 5, bar => 10, baz => 3);
 
function func($var) {
    return ($var > 5);
}
$results = array_filter($array, 'func');

Using an anonymous function could cut that down a little further:

$results = array_filter($array, create_function('$var','return ($var > 5)'));

array_filter() calls the callback function, passing it a single argument, the value of the array item being looked at. If the callback returns true, the item goes into the results that array_filter() returns.

Keys are preserved, so the following will work:

$array = array(
    'foo' => 5,
    'bar' => 7,
    'baz' => 3,
    'badger' => 10,
);
$results = array_filter($array, create_function('$var','return ($var > 5);'));
 
foreach ($results as $k => $v) {
    print "result: $k => $v\n";
}

map vs array_walk()

Perl's map can be used to run a small block of code for each element of the list it's given, and return the results as a list.

For an example, say you have a hash of value ⇒ name which is going to be used in a HTML <select> tag:

my %options = (val1 => 'Value 1', val2 => 'Value 2');
 
my @tags = map { qq[<option value="$_">$options{$_}</option>\n] } keys %options;
 
# if you're gathering together the set of HTML tags, the chances are the
# next thing you'll want to do is print them, so you could just do it in
# one go:
 
print join "\n", map { qq[<option value="$_">$options{$_}</option>] } 
    keys %options;

The above would result in @tags being a list of <option> tags, one for each item in the %options hash (or, the second example, printing out each option tag).

PHP's equivalent would be using array_walk(), again with a callback function - something like this:

function func(&$value, $key) {
	print "<option value=\"$value\">$key</option>\n";
}
array_walk($array, 'func');

[can add 3rd param to array_walk() call which is then passed to callback function as its 3rd param]

You can reduce code bloat if it's something that'll only be done once by using anonymous functions:

array_walk($array, create_function('&$value,$key', 'print $key is $value'));

for / foreach loops

Perl's for/foreach syntax is:

for my $foo (@bar) {
    ....
}
# or:
foreach my $foo (@bar) {
    ....
}

PHP's is:

# just getting values:
foreach ($bar as $foo) {
    ....
}
 
# getting keys and values:
foreach ($array as $key => $value) {
    ....
}

Perl allows for loops to be reduced to nice readable one-liners like the following, to count the number of things it found in @things:

my %table;
$table{$_}++ for @things;

An equivalent in PHP would be:

foreach ($things as $thing) {
    $table{$thing}++;
}

next vs continue

In Perl, you can jump to the next iteration through a loop with next, for example:

for my $num (1..100) {
    next if ($num % 2 == 0);
    print "$num is an odd number\n";
}

In PHP, next() gets you the next value in an array. To jump to the next iteration of a loop, you must use continue instead.

For example:

foreach (range(1,10 as $num) {
    if ($num % 2 == 0) { continue; }
    print "$num is an odd number\n";
}

anonymous functions

In PHP, you use the create_function() function to create a function, giving it two parameters - the parameters your function takes, and the code for the function:

$func = create_function('$a,$b', 'code');
 
// call as: 
$func(1, 2);

BEWARE: anon functions in PHP are really just dynamically named global functions - they don't have scope and therefore are not subject to garbage collection so the allocated RAM is never released.

Beware! This is merely a convenience function that generates a unique name for a regular function. It is *not* a closure or even an anonymous function. It is just a regular function that gets named for you.

Functions created by create_function() cannot return a value by reference.

Perl qw quote-words construct

Perl has the useful quote-words construct which makes it easy to supply a list of space-seperated items:

my @transports = qw(
    bicycle    car     motorbike
    train      plane   bus
);
# the above is the same as:
my @transports = (
    'bicycle', 'car',   'motorbike',
    'train',   'plane', 'bus'
);
# but the reduction of quotes and commas makes it a lot
# more readable

PHP doesn't have anything like that, but if you like that idea, you could always do a “rough” copy with a function like:

function qw($instr) {
// emulates (kind of) the Perl qw (quote-words) construct
// to allow a list of words to be supplied without quoting.
return (preg_split("/[\b|\s]+/",$instr));
}

Which you'd call like:

my $transports = qw('
    bicycle    car     motorbike
    train      plane   bus
');

... not quite the same, but close.

 
php/perlvphp.txt · Last modified: 2010/02/26 10:45 (external edit)
 
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki