Hi all,
I have two questions about the intended behaviour of
ArrayObject::exchangeArray() :
- What should happen when the argument is an object?
The docs suggest that the arg should be an array, but the prototype in
the code indicates objects are OK too. However, when an object is
passed, the effect is simply to remove the ArrayObject's storage
container, which doesn't seem right: http://pastebin.ca/1091256
- Should the ArrayObject store a copy or a real reference to the
array passed to exchangeArray()?
Currently, the ArrayObject container effectively becomes a
copy-on-write reference to the array passed to exchangeArray()... but
there is no logic to split the container when it is modified.
Consequently, the behaviour is very ambiguous:
http://pastebin.ca/1091266 .
Depending on the intended behaviour, it seems either exchangeArray()
needs to take its arg as prefer-by-reference, or the arg needs to be
split before being stashed in the ArrayObject.
One way to address both of these issues is to make exchangeArray()
share the logic that sets the array in __construct(). This way,
echangeArray() works with object arguments (with some special cases if
the argument is itself an ArrayObject), and array arguments are split
before being stored in the ArrayObject.
Here's a suggested patch against 5_3 that implements this (and
includes some tests): http://pastebin.ca/1091668
Note that I'm not an internals or SPL expert, so let me know if I
missed something.
Regards,
Robin
Hello Robin,
Sunday, August 3, 2008, 1:07:56 PM, you wrote:
Hi all,
I have two questions about the intended behaviour of
ArrayObject::exchangeArray() :
- What should happen when the argument is an object?
The docs suggest that the arg should be an array, but the prototype in
the code indicates objects are OK too. However, when an object is
passed, the effect is simply to remove the ArrayObject's storage
container, which doesn't seem right: http://pastebin.ca/1091256
Seems like an error message is missing there. It allows to take an instance
of another ArrayObject/Iterator and use the array from that.
In case any other Object is passed it is ignored. What do you feel?
- Should the ArrayObject store a copy or a real reference to the
array passed to exchangeArray()?
Currently, the ArrayObject container effectively becomes a
copy-on-write reference to the array passed to exchangeArray()... but
there is no logic to split the container when it is modified.
Consequently, the behaviour is very ambiguous:
http://pastebin.ca/1091266 .
Depending on the intended behaviour, it seems either exchangeArray()
needs to take its arg as prefer-by-reference, or the arg needs to be
split before being stashed in the ArrayObject.
One way to address both of these issues is to make exchangeArray()
share the logic that sets the array in __construct(). This way,
echangeArray() works with object arguments (with some special cases if
the argument is itself an ArrayObject), and array arguments are split
before being stored in the ArrayObject.
Here's a suggested patch against 5_3 that implements this (and
includes some tests): http://pastebin.ca/1091668
Note that I'm not an internals or SPL expert, so let me know if I
missed something.
Seems about right. Can you attach the patch as a text file (I cannot open
the link).
Best regards,
Marcus
Hi Marcus!
- What should happen when the argument is an object?
Seems like an error message is missing there. It allows to take an instance
of another ArrayObject/Iterator and use the array from that.In case any other Object is passed it is ignored. What do you feel?
Sounds alright to me, but it's inconsistent with __construct(), which
in addition to using the storage array from ArrayObject/Iterator
instances, can use the properties from any other kind of object. Also,
just to be clear, I should point out that it is not the current
behaviour. Passing any object to exchangeArray(), even an instance of
ArrayObject/Iterator, eradicates the container:
<?php
$ao1 = new ArrayObject(array('one'));
$ao2 = new ArrayObject(array('two'));
$ao1->exchangeArray($ao2);
var_dump($ao1);
?>
Output on PHP 5.3.0-dev (cli) (built: Jul 28 2008 00:21:59):
object(ArrayObject)#1 (0) {
}
Here's a suggested patch against 5_3 that implements this (and
includes some tests): http://pastebin.ca/1091668
Note that I'm not an internals or SPL expert, so let me know if I
missed something.Seems about right. Can you attach the patch as a text file (I cannot open
the link).
Attached. I just naively moved some logic from __construct() into a
separate function and called it from both __construct() and
exchangeArray().
Thanks!
Robin
Hello Robin,
Sunday, August 3, 2008, 10:24:17 PM, you wrote:
Hi Marcus!
- What should happen when the argument is an object?
Seems like an error message is missing there. It allows to take an instance
of another ArrayObject/Iterator and use the array from that.In case any other Object is passed it is ignored. What do you feel?
Sounds alright to me, but it's inconsistent with __construct(), which
in addition to using the storage array from ArrayObject/Iterator
instances, can use the properties from any other kind of object. Also,
just to be clear, I should point out that it is not the current
behaviour. Passing any object to exchangeArray(), even an instance of
ArrayObject/Iterator, eradicates the container:
<?php
$ao1 = new ArrayObject(array('one'));
$ao2 = new ArrayObject(array('two'));
$ao1->exchangeArray($ao2);
var_dump($ao1);
?>>
Output on PHP 5.3.0-dev (cli) (built: Jul 28 2008 00:21:59):
object(ArrayObject)#1 (0) {
}
Here's a suggested patch against 5_3 that implements this (and
includes some tests): http://pastebin.ca/1091668
Note that I'm not an internals or SPL expert, so let me know if I
missed something.Seems about right. Can you attach the patch as a text file (I cannot open
the link).
Attached. I just naively moved some logic from __construct() into a
separate function and called it from both __construct() and
exchangeArray().
Well, naively or not, this seems about perfectly correct. Why don't you
simply apply this to HEAD and 5.3?
Best regards,
Marcus
2008/8/3 Marcus Boerger helly@php.net:
Attached. I just naively moved some logic from __construct() into a
separate function and called it from both __construct() and
exchangeArray().Well, naively or not, this seems about perfectly correct. Why don't you
simply apply this to HEAD and 5.3?
Ok - done.
Thanks,
Robin