On Fri, Aug 31, 2012 at 10:24 PM, Sherif Ramadan <theanomaly...@gmail.com>wrote:

> >
> > That might actually be something I could use :) But the fun for me
> begins here:
> >
> > $numbers = array();
> > $numbers[-1] = 5;
> > $numbers[] = 6;
> >
> > What would have happened to the keys? Normally [] is equivalent to
> [count($numbers)].
> >
>
> This is incorrect, $numbers[] = 6; is not equivalent to
> $numbers[count($numbers)] = 6; at all, because PHP uses an internal
> value for this that is represented an unsigned long in the Hashtable
> ht struct.
>
> As it stands today, that code would result in the following:
>
> $numbers = array();
> $numbers[-1] = 5;
> $numbers[] = 6;
> var_dump($numbers);
> /*
> array(2) {
>   [-1]=>
>   int(5)
>   [0]=>
>   int(6)
> }
> */
>
> Which looks awkward, I know, but the reason is that the internal value
> that represents the next key to be used when no key is supplied during
> an array push is an unsigned figure while integer values in PHP are
> all signed. Since one's complement is used this means the unsigned
> value will always wrap-around causing -1 to take us back to zero (you
> can't overflow an unsigned long).
>
> Here's how we can see this quirk rearing it's ugly head:
>
> $numbers = array();
> $numbers[PHP_INT_MAX] = 'foo';
> $numbers[] = 'bar';
> var_dump($numbers);
> /*
> Warning: Cannot add element to the array as the next element is
> already occupied in ... on line 1
> array(1) {
>   [9223372036854775807]=>
>   string(3) "foo"
> }
> */
>
> As you can see PHP has a bit of a hickup here. The implementation is
> such that the index is always initialized to 0 by default and clamped
> by the API (so when a negative value is supplied we still start back
> at 0).
>
> Here's the actual implementation of array_psuh:
>
>    for (i = 0; i < argc; i++) {
>         new_var = *args[i];
>         Z_ADDREF_P(new_var);
>
>         if (zend_hash_next_index_insert(Z_ARRVAL_P(stack), &new_var,
> sizeof(zval *), NULL) == FAILURE) {
>             Z_DELREF_P(new_var);
>             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add
> element to the array as the next element is already occupied");
>             efree(args);
>             RETURN_FALSE;
>         }
>     }
>
>
>
> $array = array();
> $array[PHP_INT_MAX+1] = 'foo';
> $array[] = 'bar';
> var_dump($array);
> /*
> array(2) {
>   [-9223372036854775808]=>
>   string(3) "foo"
>   [0]=>
>   string(3) "bar"
> }
> */
>
> Another gotchya, of the API is that the representation of the key used
> in the array and the next available key can be somewhat two
> misleading.
>
> ---
>
> On a final note the confusion behind proposing the use of negative
> indexes for array lookup in PHP is that PHP doesn't really have an
> array. Something I believe has been discussed at length in the past.
> Which is why it makes sense to separate the "key" used in the array
> from the "offset" of the element in the ordered map.
>
> $array = array(-1 => "foo",0 => "bar",3 => "baz")
> array_slice($array, -1); // makes perfect sense to me that this would
> return "baz"
>
> $array = array(-1 => "foo",0 => "bar",3 => "baz")
> echo $array[-1]; // makes perfect sense to me that this would return "foo"
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>
This discussion kinda reminds me of some of the debates over AUTO_INCREMENT
behavior in the MySQL community.  Specifically, they end up having to
tackle the same funcamental, conceptual dilemma:  If I
assign/insert/whatever an arbitrary value to a container that can be
incremented, and then I direct said container to generate the next
increment, what value should that be?  What's the most sensible (or perhaps
the least unsensible) way to determine that?

Of course, I don't really know what the answer is.  From a strictly logical
standpoint (ignoring the fact that it just doesn't work this way in PHP),
my thinking would be that the count-based index approach makes the most
sense.  I think many (if not most) PHP developers incorrectly assume this
to already be the case now.

What's my point?  I'm not sure that I have one-- but if I did, the point
would be that any approach to handling this will likely be problematic in
some way or another.  That said, I think we should find a way to support
negative indexes.  There were times when being able to do that would have
been very convenient for me.  =)

--Kris

Reply via email to