-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Add Spl\ForwardArrayIterator and Spl\ReverseArrayIterator #6535
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
ce10c3e
to
c5cb87d
Compare
Some notes on the implementation:
|
I think I should switch to So yeah, I should hide the properties and use I think partly you've mis-understood the intended design. Think of these as Array -> Iterator adapters. It takes an Array and packages it into an Iterator API for use in places where you specifically need an iterator (as I showed in the example in the original post). If we add array-specific features then it's leaking through the API. There may be exceptions to this -- for instance, a method like By the way,
There aren't "holes" in the iterator, by the way. The array iterator reports what the array has: $x = ['a','b','c']; unset($x[1]);
$iterator = new Spl\ForwardArrayIterator($x);
foreach ($iterator as $key => $current) {
echo "[{$key} => {$current}]\n";
}
/* results in:
[0 => a]
[2 => c]
*/ |
e7d3942
to
db8683c
Compare
I did the following in recent commits:
Thanks @TysonAndre for the review! |
ForwardArrayIterator *iterator = ArrayIterator_from_obj(Z_OBJ_P(ZEND_THIS)); | ||
zval *current = ForwardArrayIterator_current(iterator); | ||
if (EXPECTED(current)) { | ||
ZVAL_COPY(return_value, current); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the implementation of ForwardArrayIterator_current and ReverseArrayIterator_current need a call to ZVAL_DEREF? What happens for code such as the following - will $v unintentionally be a reference?
$z = 2;
$y = [&$z];
$x = new SplForwardArrayIterator($y);
foreach ($x as $k => $v) {
$v = 'new value';
}
var_dump($z);
E.g. elsewhere in spl_array.c, I see the following (The IS_INDIRECT check may have become unnecessary now that $GLOBALS can't be passed directly to methods in php 8.1, ask nikita - that snippet also seems to support object property tables (IS_OBJECT) which definitely have IS_INDIRECT)
if ((entry = zend_hash_get_current_data_ex(aht, spl_array_get_pos_ptr(aht, intern))) == NULL) {
RETURN_FALSE;
}
if (Z_TYPE_P(entry) == IS_INDIRECT) {
entry = Z_INDIRECT_P(entry);
}
ZVAL_DEREF(entry);
RETURN_BOOL(Z_TYPE_P(entry) == IS_ARRAY || (Z_TYPE_P(entry) == IS_OBJECT && (intern->ar_flags & SPL_ARRAY_CHILD_ARRAYS_ONLY) == 0));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am unsure on the deref. I'll think on it some more, but you might be right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think a DEREF is needed -- at least as written I get int(2)
. In the back of my head by-value is taken care of by the iteration API somewhere; I think the VM will do zend_copy_to_variable
. However, as Joe Watkins told me, it is a cheap operation to perform to be sure. Maybe extensions will call this API and not doing the DEREF would be a problem. I've convinced myself you are right about the DEREF, I think.
I don't know much about indirect. @nikic , can you chime in there?
e2c46c8
to
1da65a5
Compare
ForwardArrayIterator is a simple array iterator which does not dup the array (though if the user modifies it after making an iterator then normal copy-on-write will apply and make a copy then). The ForwardArrayIterator API is intentionally very small.
1da65a5
to
3b041cd
Compare
I'm going to close this (thanks GH for pinging me...) I'm not against this feature per se, but I don't think it should use Please reopen, or open a new PR if this is still something that is being considered. |
Spl\ReverseArrayIterator
Spl\ReverseArrayIterator
iterates over the array in reverse order, preserving keys.Spl\ForwardArrayIterator
ForwardArrayIterator is a simple array iterator which does not dup the array (though if the user modifies it after making an iterator then normal copy-on-write will apply and make a copy then). It iterates over the array in order. The API is intentionally very small. In contrast,
ArrayIterator
has a large API which requires it to almost always duplicate the array.Spl\ForwardArrayIterator
is intended to replace many usages ofnew \ArrayIterator($array)
where iterating over the array in an iterator form is the intended use case. It is not intended to replace other usages, such asArrayIterator::sort
.For such simple cases I recommend using the
$array
directly, but sometimes an iterator is needed for generic code, such as:Status