php


So Tyler says to me, he says:

I went to the Nashville PHP group last night. The conversation turned to which languages are on the rise, and I threw Python into the mix. Problem is, I had very little ammo to arm myself with. Got a list of bullet points as to why Python is better?

Well, yes and no.

In terms of functionality, there’s very little difference between Perl 5, Python, PHP and Ruby. The reasons to choose one over the other are typically very domain-specific (hence subtle and of little use when fighting religious wars): Perl 5 makes text munging simple by having, e.g., regular expressions as first-class citizens; PHP makes web applications more natural because, well, that’s what it was designed to do.

I have nothing really positive (or negative) to say about Ruby. I can’t think of any special niche that it fills. Anonymous blocks? Perl 5 has them. Pure OO? Python has it. call/cc? If you think you need continuations, you probably don’t. You could argue that Ruby serves a purpose by combining all these things, but the number of people who sincerely need a pure OO language with anonymous blocks and continuations is probably around five.

The negative things I can think of with respect to Perl 5 and PHP is that it’s hard to do dependency injection-based testing in these languages. It’s so hard in Java, for example, even Google has invented a tool to make Java DI easier. Python on the other hand makes this dead-simple, making it so much easier to test your code from all perspectives. Hell, it’s so easy in Python, I didn’t even know there was a name for it until I came to Google. I don’t know how easy DI is in Ruby, but if it’s not Python-easy, Ruby loses.

That’s one criterion for programming languages that I don’t see discussed much: ranking languages by how easy the code is to test. One frequent example is mocking a global resource like a time source. C, C++ and Java all require you to come up with unnatural function signatures or link against special libraries when testing in order to gain control over time. It’s easier in Perl 5, but it still requires a good deal of specialized knowledge of how namespaces and module lookups work. Assuming the target library does something like import time at the top, here’s how you take control of a given module’s time source in Python:

>>> import some_module
>>> class StubTime:
>>>    def time(self):
>>>        return 3634634
>>> some_module.time = StubTime()

Done. No specialized knowledge of interpreter details, no crazy setup, just done. If mocking global resources isn’t that easy in PHP, Ruby or any other language, I have little use for it beyond toy projects. Testing is where I feel Python really stands out.

Up until a few weeks ago, I had used PHP only a handful of times, generally when tinkering with WordPress. That was up until I started my current job, maintaining a terrible content management “system” written in a mixture of PHP and perl.

What kicked this client from “suck” to “kill me now” was having to deal with PHP. I hate this language. So. Much. The office can tell when I’m working on this project from the stream of profanity alone.

The current version of my “Why PHP is destroying my soul little by little” list:

  • You can’t write something like get_active_subscription($user)->subscription_type. You first have to assign the return value of get_active_subscription() to an intermediate variable, then grab the subscription_type attribute from that intermediate. The same thing goes for array subscription.

  • PHP’s three billion functions were named by someone on psychotropic drugs. As evidence: count v strlen v count_chars v str_word_count. Quick — what’s the difference?

  • $some_object->nonexistant_attribute evaluates to the empty string.

  • $misspelled_variable evaluates to the empty string.

  • Pushing a value on to an array is spelled $arr[] = $object. You’re right, that is better than a function (perl’s push @array, $object) or a method (python’s list.append(object)).

  • The incredibly consistent naming scheme for functions. My favorite examples are the array_* and *_array functions.

  • My absolute favorite comes from the PHP manual, talking about why you shouldn’t use barewords to index an array, i.e., $foo[bar] instead of $foo["bar"]:

    [Using a bareword] is wrong, but it works. Then, why is it wrong? The reason is that this code has an undefined constant (bar) rather than a string. and PHP may in future define constants which, unfortunately for your code, have the same name. It works because PHP automatically converts a bare string (an unquoted string which does not correspond to any known symbol) into a string which contains the bare string. For instance, if there is no defined constant named bar, then PHP will substitute in the string ‘bar’ and use that.

    Brilliant.

  • You can use return outside of functions without PHP complaining.

  • The entire array() class. Everything about it. Absolutely everything. I’ve been using it for a month, and I still don’t feel comfortable with the thing’s semantics.

  • From the docs for array_diff(): “Two elements are considered equal if and only if (string) $elem1 === (string) $elem2. In words: when the string representation is the same.”

    Best. Equivalence test. Ever.

  • Writing $a = $b || $c gives you a boolean, not the value of $b or $c like some more useful languages I can think of.

I’m still debating what conclusion to draw about PHP. I can’t decide whether it’s the diseased creation of a bunch of retards gone off their meds, or if it’s one of the most successful and widespread practical jokes ever conceived (”Let’s see how many people we can get to use this piece of shit!” “Dude, that’s awesome!”).