PHP is stupid, yet again

xsawyerx on 2009-08-17T11:17:39

The developers at my $work already know I hate PHP with a passion (and most of them do too). Here is a nugget of... I'll let you decide, that shows another interesting... err.. uh... feature?

php > $a = array('a','b','c');
php > unset($a[1]);
php > var_dump($a);
array(2) {
  [0]=>
  string(1) "a"
  [2]=>
  string(1) "c"
}

What you see here is setting a variable in a PHP REPL shell. The variable is an array. Then we remove the second element in the array (index no. 1) and then dump the array with the indexes.

Do you see the problem? Let me iterate further (excuse the pun). When you remove the second element in an array, you would expect the third to now become the second, the fourth becoming the third, and so on. First of all, because it makes perfect sense. Secondly, when you iterate over the array, you don't have any holes and gaps, causing segfaults or unexpected behavior (at the worst case) or exceptions raised (at the best case). Did I mention possible security problem?

However, apparently in PHP, you can remove an element from an array and the array will act like a hash with the indexes as the keys. It will maintain the old index and not update it.

Perl, on the contrary...

In Perl, the way to do this wouldn't be to undef the variable but to splice it out. Splicing it correctly sets the indexes of every element and makes sure it's done right. It even returns the value if you want it, or just replaces it inline with another. However, suppose that PHP has a way to do this as well, the above result is still fscked up. This is what would happen if I decide to simply undef an array element in Perl (demonstrated in Devel::REPL:

$ my @a = ( qw( a b c ) );
$ARRAY1 = [
            'a',
            'b',
            'c'
          ];
$ undef $a[1];
$ @a
$ARRAY1 = [
            'a',
            undef,
            'c'
          ];

It keeps the index and the indexed item, but the value is undefed.


this doesn't bother me

rjbs on 2009-08-17T21:03:42

Perl has foibles like this, too:

  DB<1> @a = (1,2,3)
  DB<2> delete $a[1]
  DB<3> x \@a
0  ARRAY(0x90a6d0)
   0  1
   1  empty slot
   2  3

..and PHP has exactly what you suggested.

<? $x = array(1,2,3); array_splice($x, 1, 1); var_dump($x); ?>
array(2) {
  [0]=>
  int(1)
  [1]=>
  int(3)
}

Just because PHP is often intolerable doesn't mean that everything it does is wronger than Perl.

I think you misunderstood

xsawyerx on 2009-08-18T08:06:03

PHP removes the index, which is the problematic part. Your Perl example shows exactly what my Perl example shows, which is that Perl just puts the value on undef and keeps the index, so you can iterate without a problem. This is far from a foible and is the correct and best result. This is not a Perl "feature", Python and Ruby behave the exact same way. PHP is the different here, and it is indeed stupid.

$ my @a = (1, 2, 3)
$ARRAY1 = [
            1,
            2,
            3
          ];
$ delete $a[1];
$ @a
$ARRAY1 = [
            1,
            undef,
            3
          ];
$ print "nay\n" if !$a[1];
nay

In PHP this would cause an error since there is no $a[1]. That was my point.

Just because PHP is often intolerable doesn't mean that everything it does is wronger than Perl.

I'm not saying everything PHP does it wrong (or wronger than Perl), but I'm saying it often opts for the stupid way out. This includes removing indexes and leaving you with gaps in your arrays (which was my point on this post), throwing exceptions on build-in functions, adding goto as a "new feature" for a very high level language, and so so so many more examples we all pitch.

The reason for this is...

bart on 2009-08-18T11:33:57

... because in PHP, an array and a hash are the same thing.

It has its uses. Though often, it'll just bite you in the ass.

Re:The reason for this is...

xsawyerx on 2009-08-18T11:37:15

Agreed.