Tuesday, May 6, 2008

php vs perl

"PHP IN CONTRAST TO PERL"

This document is http://tnx.nl/php - If you replicate it, please do link. Trust HTTP headers for last-modified info. Corrections and additions are welcome at geeks#@tnx.nl.

Despair-like poster: PHP, Training Wheels without the Bike

PHP is a nice tool for adding dynamic parts to a small website. It is popular because it integrates very well with the popular Apache webserver, but also because the basics of PHP are very easy to learn. But is it wise to build applications or large websites with PHP? Perhaps Perl is a better solution.

This document compares PHP to Perl, because its author is very familiar with these two languages. It would be nice if others could write comparisons to Ruby, Python, and other dynamic programming languages.

A follow-up document is available, at http://tnx.nl/php5.

Table of contents

Arguments and return values are extremely inconsistent

To show this problem, here's a nice table of the functions that match a user defined thing: (with something inconsistent like this, it's amazing to find that the PHP documentation doesn't have such a table. Maybe even PHP people will use this document, just to find out what function to use :P)

                         replaces case                 gives   s/m/x offset
matches with insens number arrays matches flags (-1=end)
ereg ereg no all no array no 0
ereg_replace ereg str no all no no no 0
eregi ereg yes all no array no 0
eregi_replace ereg str yes all no no no 0
mb_ereg ereg[1] no all no array no 0
mb_ereg_replace ereg[1] str/expr no all no no yes 0
mb_eregi ereg[1] yes all no array no 0
mb_eregi_replace ereg[1] str yes all no no no 0
preg_match preg[2] yes/no one no array yes 0
preg_match_all preg yes/no all no array yes 0
preg_replace preg str/expr yes/no n/all yes no yes 0
str_replace str str no all yes number no 0
str_ireplace str str yes all yes number no 0
strstr, strchr str/char no one no substr no 0
stristr str/char yes one no substr no 0
strrchr char no one no substr no -1
strpos str/char no one no index no n
stripos str/char yes one no index no n
strrpos char[3] no one no index no n
strripos str yes one no index no -1
mb_strpos str[1] no one no index no n
mb_strrpos str[1] yes one no index no -1

The problem exists for other function groups too, not just for matching.

(In Perl, all the functionality provided by the functions in this table is available through a simple set of 4 operators.)

[1] Handles multi-byte characters
[2] PCRE regex: so-called "Perl compatible" regular expressions.
[3] Also does strings in PHP 5

PHP has separate functions for case insensitive operations

(This can be argued both ways. Some think it's good to have functions that combine functions, even if that means having dozens of extra names to remember)

In Perl, you use a double lc() (lowercase) or the /i flag where PHP usually provides a case insensitive variant. The case-insensitive versions have very inconsistent naming.

Perl: $foo cmp $bar                            lc $foo cmp lc $bar
PHP: strcmp($foo, $bar) strcasecmp($foo, $bar)

Perl: index($foo, $bar) index(lc $foo, lc $bar)
PHP: strpos($foo, $bar) stripos($foo, $bar)

Perl: $foo =~ s/foo/bar/ $foo =~ s/foo/bar/i
PHP: $foo = str_replace('foo', 'bar', $foo) $foo = str_ireplace(...)
PHP: $foo = ereg_replace('foo', 'bar' ,$foo) $foo = eregi_replace(...)

PHP has inconsistent function naming

  • Case insensitive functions have the 'i' or 'case' at different positions in their names.
  • There is no apparent system in underscore(s) versus no underscore(s):
    underscore               no underscore:

    stream_get_line readline
    disk_free_space diskfreespace
    is_object isset
    mcal_day_of_week jddayofweek
    set_error_handler setlocale
    snmp_get_quick_print snmpget
    get_browser getallheaders
    base64_encode urlencode
    image_type_to_mime_type imagetypes
    msql_num_fields mysql_numfields
    php_uname phpversion
    strip_tags stripslashes
    bind_textdomain_codeset bindtextdomain
    cal_to_jd gregoriantojd
    str_rot13 strpos
    Perl has no core function names with underscores in them.
  • PHP has unlink, link and rename (system calls), but touch (the system call is utime, not touch).
  • And they can't decide on word order:
    • object verb: base64_decode, iptcparse, str_shuffle, var_dump
    • verb object: create_function, recode_string

    Perl core functions are all "verb object" except the superseded dbm* functions. (Note that sys is a prefix, not an object. And that flock and lstat were named after the system calls. shm* and msg* are library calls)

  • "to" or "2"?

    ascii2ebcdic, bin2hex, deg2rad, ip2long, cal_to_jd (jdto*, *tojd), strtolower, strtotime,

PHP has no lexical scope

Perl has lexical scope and dynamic scope. PHP doesn't have these.

For an explanation of why lexical scope is important, see Coping with Scoping.

                       PHP  Perl
Superglobal Yes Yes [1]
Global Yes Yes
Function local Yes Yes [2]
Lexical (block local) No Yes
Dynamic No Yes

[1] Perl has variables that are always in the main:: namespace. These are like PHP's superglobals.
[2] Using a lexical variable in a sub routine's block, you get a function local variable.

PHP has too many functions in the main namespace

(Using the core binaries compiled with all possible extensions in the core distribution, using recent versions in November 2003.)

Number of PHP  main functions: 3079 [1]
Number of Perl main functions: 206 [2]
Median PHP  function name length: 13
Mean PHP function name length: 13.67
Median Perl function name length: 6
Mean Perl function name length: 6.22

Note that Perl has short syntax equivalents for some functions:

readpipe('ls -l') ==> `ls -l`
glob('*.txt') ==> <*.txt>
readline($fh) ==> <$fh>
quotemeta($foo) ==> "\Q$foo"
lcfirst($foo) ==> "\l$foo" (lc is \L)
ucfirst($foo) ==> "\u$foo" (uc is \U)

[1] Source: PHP Quick Reference
[2] Source: perldoc perlfunc

PHP lacks abstraction and takes TIMTOWTDI to bad extremes

Why has PHP got 3079 functions while Perl does with only 206? In PHP, there are usually several functions that are very similar. In Perl, you have to know and remember less.

Another important factor is the use of modules, especially the DBI module which provides support for SQL databases, instead of bloating the core with lots of features that occupy memory but are rarely used.

(Modules that are more often not used than used don't count (This rules out PEAR for PHP and IO::File for Perl). Modules may be pulled in when the core provides no similar functionality. For simplicity, internal working is left out of this comparison.)

* Escaping:

* PHP: (14)
dbx_escape_string, escapeshellarg, escapeshellcmd, pg_escape_bytea,
pg_escape_string, pg_unescape_bytea, addslashes, addcslashes, preg_quote,
quotemeta, mysql_escape_string, mysql_real_escape_string,
mysqli_real_escape_string, sqlite_escape_string

* Perl: (2) [1]
quotemeta, $dbh->quote

* Sorting:

* PHP: (16)
sort, arsort, asort, krsort, ksort, natsort, natcasesort, rsort, usort,
array_multisort, uasort, uksort, dbx_sort, imap_sort, ldap_sort, yaz_sort

* Perl: (1)
sort

* Walking a list

* PHP: (10)
array_filter, preg_grep, array_search, array_unique, in_array, array_map,
array_walk, array_count_values, array_change_key_case, array_sum

* Perl: (2)
map, grep

* Splitting:

* PHP: (8)
split, explode, strtok, spliti, chunk_split, mb_split, preg_split,
str_split

* Perl: (1)
split

* Matching:

* Strings:

* PHP: (11)
strstr, strchr, stristr, strpos, strrchr, stripos, mb_strpos,
mb_strrpos, strrpos, strripos, substr

* Perl: (3)
index, rindex, substr

* Regular expressions:

* PHP: (6)
ereg, eregi, mb_ereg, mb_eregi, preg_match, preg_match_all

* Perl: (1)
m//

* Substituting a matched part:

* PHP: (12)
ereg_replace, eregi_replace, mb_ereg_replace, mb_eregi_replace,
preg_replace, str_ireplace, str_replace, ltrim, rtrim, trim, nl2br

* Perl: (1)
s///

* Connecting to an SQL database:

* PHP: (17)
dbx_connect, fbsql_connect, ibase_connect, msql_connect, msql_pconnect,
mssql_connect, mysql_connect, odbc_connect, pg_connect, pg_pconnect,
sesam_connect, ifx_pconnect, ifx_connect, sqlite_open, sqlite_popen,
mysqli_connect, mysqli_pconnect

* Perl: (2)
DBI->connect, DBI->connect_cached

* Opening:

* PHP: (5)
dio_open, fopen, proc_open, popen, gzopen[2]

* Perl: (2)
open, sysopen

* Reading/receiving:

* PHP: (12)
dio_read, fread, gzread[2], socket_read, socket_recv, socket_recvfrom,
socket_recvmsg, readline, fgetc, fgets, stream_get_line, file

* Perl: (5)
read, readline, sysread, recv, getc

* Printing/writing:

* PHP: (14)
print, echo, printf, fprintf, vprintf, dio_write, fwrite, fputs,
gzwrite[2], socket_send, socket_sendmsg, socket_sendto, socket_write,
socket_writev

* Perl: (5)
print, printf, syswrite, send, write

* Closing:

* PHP: (7)
closelog, dio_close, fclose, gzclose[2], pclose, socket_close,
proc_close

* Perl: (1)
close

* Miscellaneous:

* PHP:
array_combine, array_fill, array_merge, list, range, count,
create_function, strtr, pow, putenv, getenv, getmygid, getmypid, getmyuid

* Perl:
syntax or magic variables

[1] Because of system LIST syntax and DBI's placeholders, explicit escaping is usually not even needed.
[2] Handled in Perl by a PerlIO layer

  • Re^2: Is Perl a good career move? by Juerd, 2005
    • Still no namespaces
    • No closures, not even anonymous functions
    • No good HTML parser
    • No easy MIME builder
    • No good WWW library
    • No CPAN
    • No arrays
    • Less useful logical operators
  • Yaywoo! by Dave Brown, 2004
    • No way to avoid the (unsafe) shell with system()
    • XY-problem
    • Huge proliferation of different functions to do more-or-less the same thing with minor variations
    • Second parameter and return value make no sense
    • Bad spelling in function names
  • Why PHP sucks by Edwin Martin, 2004
    • Bad recursion support
    • PHP is not thread safe
    • PHP is crippled for commercial reasons
    • No namespaces
    • Non-standard date format characters
    • Confusing licenses
    • Inconsequent function naming convention
    • Magic quotes hell
  • Perl vs. PHP - octo's subjektiver Vergleich by Florian Forster, 2003 (German)
    • Perl is faster than PHP
    • Perl is more versatile than PHP
    • Perl has better documentation than PHP
    • PHP lacks support for modules
    • PHP's here-docs are useless for Windows users
    • PHP lacks a consistent database API
    • PHP dangerously caches database query results
    • For graphics, PHP is practically limited to GD
  • I hate PHP by Keith Devens, 2003
    • Idiotic call-time pass-by-reference deprecation
  • Experiences of Using PHP in Large Websites by Aaron Crane, 2002
    • PHP promotes interweaving presentation with business logic
    • Not having namespaces causes problems
    • Global configuration with php.ini
    • Oversimplification leads to excessive complexity
  • PHP Annoyances by Neil de Carteret, 2002
    • No real references or pointers
    • No idea of namespace
    • No componentization
    • Wants to be Perl, but doesn't want to be Perl
    • No standard DB interface
    • All PHP community sites are for non-programmers
    • No chained method calls (Not true anymore --tnx.nl)
    • No globals except by importation
    • Both register_globals and $_REQUEST bite
    • Arrays are hashes
    • PEAR just ain't CPAN
    • Arrays cannot be interpolated into strings
    • No "use strict" like checking of variable names
  • PHP: A love and hate relationship by Ivan Ristic, 2002 (Mirrored locally, original link is dead)
    • The community gets on my nerves
    • Knowledgeable people are in a serious minority
    • Zend publishes articles suggesting insecure practice
  • My list of PHP shortcomings by Nathan Torkington, 2001
    • No namespaces
    • All functions are global
    • No real references
    • No real data structures (Not true anymore --tnx.nl)
    • No anonymous functions

Quotes

Slashdot, BBC creates 'Perl on Rails': I am going to create "PHP off the Rails" for developers of PHP websites. PHP developers will need no training, as most of them are off the rails already! -- Anne Thwacks

EFnet #php: 19:45 <+Dragnslcr> Comparing PHP to Perl is like comparing pears to newspapers

Perl Monks: PHP - it's "training wheels without the bike" -- Randal L. Schwartz

lesscode.org: PHP has a very low barrier to entry; consequently, a lot of eye-wateringly bad programmers are writing code in it; hence, a lot of code written in PHP is awful. This is arguably a good thing. -- Aristotle Pagaltzis

use Perl;: We all know that, due to the poor design of the language, security and PHP applications don't mix well, because PHP makes writing secure code difficult; apparently security doesn't mix well either with the mindset of the PHP core developers. -- Rafael Garcia-Suarez

Perl Buzz: Sure, PHP 6 may have a shorter release cycle than Perl 6 has, but at the end of it all, we'll have Perl 6, and you'll still have PHP. Just sayin'. -- Andy Lester

FOSDEM: :I chose PHP because I thought it would be a better fit for the community I was targeting, which tended to have a lot of non-programmers in it. -- Patrick Michaud

No comments:

Post a Comment