Having thought about this for a while, I think this is a bad idea - here's why:
$array = array(1001, 1002, 1003, 1004);
$number = $array[-1]; // => 1004
$number[-1] = 1005;
$number = $array[-1]; // => ????
Obviously, the last statement must return 1005, since otherwise that
value would be inaccessible.
On the other hand, to know whether you have to know whether your array
is currently a hash or not - since array index now works completely
differently depending on whether your array is currently a hash or an
array.
This is not something you can currently even test for - and not
something you should really need to know or care about in the first
place. Having to know this information in certain cases would defeat
the purpose of having a single collection-type in the first place: it
really should work the same, all the time.
Just my $0.02...
Having thought about this for a while, I think this is a bad idea - here's
why:$array = array(1001, 1002, 1003, 1004); $number = $array[-1]; // => 1004 $number[-1] = 1005; $number = $array[-1]; // => ????
Obviously, the last statement must return 1005, since otherwise that
value would be inaccessible.
maybe you wanted to write
$array[-1] = 1005;
instead of
$number[-1] = 1005;
?
otherwise I can't see the problem that you are mentioning.
could you clarify?
--
Ferenc Kovács
@Tyr43l - http://tyrael.hu
Yes, typo! sorry.
$array = array(1001, 1002, 1003, 1004);
$number = $array[-1]; // => 1004
$array[-1] = 1005;
$number = $array[-1]; // => ????
Looking at the resulting code, I would like to point out also that
it's extremely misleading... because $array[-1] references two
completely different elements depending on whether you're reading or
writing the value... unless $array[-1] = 1005 would actually overwrite
the last element in the array - in which case it gets even more
dangerous, as well as breaking backwards compatibility...
Having thought about this for a while, I think this is a bad idea - here's
why:$array = array(1001, 1002, 1003, 1004); $number = $array[-1]; // => 1004 $number[-1] = 1005; $number = $array[-1]; // => ????
Obviously, the last statement must return 1005, since otherwise that
value would be inaccessible.maybe you wanted to write
$array[-1] = 1005;
instead of
$number[-1] = 1005;
?otherwise I can't see the problem that you are mentioning.
could you clarify?--
Ferenc Kovács
@Tyr43l - http://tyrael.hu
Yes, typo! sorry.
$array = array(1001, 1002, 1003, 1004); $number = $array[-1]; // => 1004 $array[-1] = 1005; $number = $array[-1]; // => ????
Looking at the resulting code, I would like to point out also that
it's extremely misleading... because $array[-1] references two
completely different elements depending on whether you're reading or
writing the value... unless $array[-1] = 1005 would actually overwrite
the last element in the array - in which case it gets even more
dangerous, as well as breaking backwards compatibility...
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)].
Perhaps this is why JS treats negative indices as properties instead :)
Having thought about this for a while, I think this is a bad idea - here's
why:$array = array(1001, 1002, 1003, 1004);
$number = $array[-1]; // => 1004
$number[-1] = 1005;
$number = $array[-1]; // => ????
Obviously, the last statement must return 1005, since otherwise that
value would be inaccessible.maybe you wanted to write
$array[-1] = 1005;
instead of
$number[-1] = 1005;
?otherwise I can't see the problem that you are mentioning.
could you clarify?--
Ferenc Kovács
@Tyr43l - http://tyrael.hu
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"
On Fri, Aug 31, 2012 at 10:24 PM, Sherif Ramadan theanomaly.is@gmail.comwrote:
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"--
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
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
I really think people are misunderstanding both the problem and the
solution here so I will try to make this very simple.
-
Problem: Finding an element in a PHP array by its offset
-
Solution: array_slice($array, -1)
-
Confusion: Array offsets are not indexes or array keys
-
Deep confusion: $array[-1] can be used to access an element by its offset
-
Twilight Zone: PHP Arrays are ordered by their keys
The problem here is not that PHP doesn't support or allow you to
access the element in an array by its offset or that a negative offset
can't reach into the bottom/end of the array. The problem is that
people are confusing an offset with an index. PHP arrays have keys.
The $array[<key>] syntax allows us to access an array element by its
key, not by its offset. The reason is simple: PHP Arrays are ordered
hashmaps (they are made up of ordered key/value pairs). To confuse
people now by modifying this syntax to allow you to do what
array_slice()
already does perfectly well, would make using the same
syntax for accessing array values by their keys impossible.
Sherif Ramadan wrote:
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)
}
*/
I think that it is just clarifying this further by adding
$numbers = array(0,1,2,3,4);
Which gives
array(7) { [0]=> int(0) [1]=> int(1) [2]=> int(2) [3]=> int(3) [4]=> int(4)
[-1]=> int(5) [5]=> int(6) }
and
foreach( $numbers as $value ) { print($value); } gives 0123456 as I would have
expected!
AND print( $numbers[-1] ); still returns '5'
I can NOW use ksort()
to really move the '5' to the top of the list.
array(7) { [-1]=> int(5) [0]=> int(0) [1]=> int(1) [2]=> int(2) [3]=> int(3)
[4]=> int(4) [5]=> int(6) }
Bottom line ... perhaps we need a DIFFERENT means of identifying position in the
array since using -ve keys IS a valid situation in real life. Personally I use
-ve positions in the database tables to save having to process all records when
adding items at the top, so the associative array quite correctly has -ve key
values. I would not want PHP screwing around with that when reading the array in :)
I think I am right in saying that 'real array' always start at 0 or 1, and
positioning is explicit. So for simple stings then ne6ative indexes make perfect
sense. But for PHP 'container arrays' we can legally have -ve keys, and removing
that is simply not acceptable.
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
Sherif Ramadan wrote:
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)
}
*/I think that it is just clarifying this further by adding
$numbers = array(0,1,2,3,4);
Which gives
array(7) { [0]=> int(0) [1]=> int(1) [2]=> int(2) [3]=> int(3) [4]=> int(4)
[-1]=> int(5) [5]=> int(6) }
I have no idea how it would. I think you supplied the wrong code here.
and
foreach( $numbers as $value ) { print($value); } gives 0123456 as I would
have expected!
AND print( $numbers[-1] ); still returns '5'I can NOW use
ksort()
to really move the '5' to the top of the list.
array(7) { [-1]=> int(5) [0]=> int(0) [1]=> int(1) [2]=> int(2) [3]=> int(3)
[4]=> int(4) [5]=> int(6) }Bottom line ... perhaps we need a DIFFERENT means of identifying position in
the array since using -ve keys IS a valid situation in real life. Personally
I use -ve positions in the database tables to save having to process all
records when adding items at the top, so the associative array quite
correctly has -ve key values. I would not want PHP screwing around with that
when reading the array in :)
I can't understand what you mean by "Different means of identifying
position in the array"? If you mean a way to access an array's element
by its position in the array then yes, we already have that. It's
called array_slice()
see http://php.net/array-slice which allows you
to access elements in the array by their offset and that includes
using a negative offset. The key and the offset are two completely
different things.
I think I am right in saying that 'real array' always start at 0 or 1, and
positioning is explicit. So for simple stings then ne6ative indexes make
perfect sense. But for PHP 'container arrays' we can legally have -ve keys,
and removing that is simply not acceptable.
Yes, the position is always explicit, the key isn't ever responsible
for determining the position of an element in the array. The value of
the PHP key has never been responsible for determining the position of
the element in the array.
$array[99999] = 'first element';
$array[0] = 'second element';
var_dump($array);
/*
array(2) {
[99999]=>
string(13) "first element"
[0]=>
string(14) "second element"
}
*/
$array[0] = 'first element';
$array[99999] = 'second element';
var_dump($array);
/*
array(2) {
[99999]=>
string(14) "second element"
[0]=>
string(13) "first element"
}
*/
The order has always been determined internally so the values of these
keys mean nothing in terms of order as you can see.
--
Lester Caine - G8HFLContact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
$array[0] = 'first element';
$array[99999] = 'second element';
var_dump($array);
/*
array(2) {
[99999]=>
string(14) "second element"
[0]=>
string(13) "first element"
}
*/
Just correcting this as it was a copy/paste fail... The above code
would produce:
array(2) {
[0]=>
string(13) "first element"
[99999]=>
string(14) "second element"
}
Sherif Ramadan wrote:
I can't understand what you mean by "Different means of identifying
position in the array"? If you mean a way to access an array's element
by its position in the array then yes, we already have that. It's
calledarray_slice()
seehttp://php.net/array-slice which allows you
to access elements in the array by their offset and that includes
using a negative offset. The key and the offset are two completely
different things.
Never had to use it ;) But then there is a heck of a lot of stuff I've never
even looked at.
But it does blow this thread - when referring to collection arrays - out of the
water? The problem I see is people trying to apply 'string' rules in the wrong
way ... and I find that string handling works fine for me as it currently works
but we probably just need to STOP people trying to apply the same rules to
something that is totally different? And I though that 'string' -ve indexes had
been sorted?
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
Lester Caine wrote:
Sherif Ramadan wrote:
I can't understand what you mean by "Different means of identifying
position in the array"? If you mean a way to access an array's element
by its position in the array then yes, we already have that. It's
calledarray_slice()
seehttp://php.net/array-slice which allows you
to access elements in the array by their offset and that includes
using a negative offset. The key and the offset are two completely
different things.Never had to use it ;) But then there is a heck of a lot of stuff I've never
even looked at.
But it does blow this thread - when referring to collection arrays - out of the
water? The problem I see is people trying to apply 'string' rules in the wrong
way ... and I find that string handling works fine for me as it currently works
but we probably just need to STOP people trying to apply the same rules to
something that is totally different? And I though that 'string' -ve indexes had
been sorted?
OK ... got back form the weekly chore of shopping, and was thinking about what I
had said :)
"Different means of identifying position in the array"? I was probably thinking
more along the lines of $numbers[-1] is a perfectly valid key on that array, so
there is no way that it can be redefined otherwise. It would have to be
something completely different such as $numbers[(-1)] to differentiate from the
normal use of a key in the array ... and I would have to object strongly to
adding that since it is different to other methods. The problem here was
accepting that [-1] works differently on a string, and now we are seeing the
consequences? It is only valid on a string and so this discussion needs a big
brick wall between strings and 'collection arrays' ?
People who think they need a position based indexing obviously need educating in
the use of the array_slice and the other functions that seem to go with that,
but I can see that this method of handling array indexes ( rather than keys )
COULD benefit from a tidy up. As has been discussed in general on the whole
array API?
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk