Req #80120 [Fbk->Nab]: ForEach() backwards support?
| From: | requinix@php.net | Date: | Fri, 18 Sep 2020 19:59:09 +0000 |
| Subject: | Req #80120 [Fbk->Nab]: ForEach() backwards support? | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-229080@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=80120&edit=1
ID: 80120
Updated by: requinix@php.net
Reported by: divinity76 at gmail dot com
Summary: ForEach() backwards support?
-Status: Feedback
+Status: Not a bug
Type: Feature/Change Request
Package: *General Issues
PHP Version: Next Minor Version
Block user comment: N
Private report: N
New Comment:
> there's no place where iterating forward manually is "too hard" either, right?
> ^^
You know that the alternative is using reset() + next() + key() + current()?
So yes, it *is* too hard to do that manually :p
If you feel strongly that a reverse-foreach would be beneficial to PHP then you should spend some
time thinking about exactly how it would work, and when you're ready to talk about it you can
hit up the internals mailing list with your ideas.
https://wiki.php.net/rfc/howto
Otherwise, given (1) there is no blatantly obvious syntax for this new foreach behavior to use, (2)
it won't work with iterators/generators, and (3) the alternative of a for loop or
array_reverse() isn't too complicated to ask for, I don't think this will work out.
(more on #2: a reverse foreach could automagically call iterator_to_array() and array_reverse(),
however there are too many times when that isn't safe to do; PHP cannot detect an infinite
iterator, or one that has unpleasant side effects, or one that would consume too much memory if
everything were collected at once, so it needs to be up to the developer to decide how to proceed.
Perhaps the best solution to reversing the data lies with an ORDER BY x DESC, or calling an API with
a sort=desc parameter?)
Previous Comments:
------------------------------------------------------------------------
[2020-09-18 17:19:40] divinity76 at gmail dot com
@requinix
> For one, this isn't going to work with iterators. Those can only run in one direction.
huh, that's a good point. probably won't work with generators/yield either (especially
infinite generators with a foreach() containing break; or return; )
> Is there a case where it's "too hard" to do it in reverse manually?
no, not really, there's just cases where foreach() would be easier, and that's the reason
foreach() exist in the first place; there's no place where iterating forward manually is
"too hard" either, right? ^^
------------------------------------------------------------------------
[2020-09-18 16:20:02] requinix@php.net
For one, this isn't going to work with iterators. Those can only run in one direction.
But I'm not sure why this needs to be a feature. It's not hard to set up for loops on
arrays, and with iterators there's iterator_to_array + array_reverse (if you know it's
safe to do so). Is there a case where it's "too hard" to do it in reverse manually?
------------------------------------------------------------------------
[2020-09-18 08:33:26] divinity76 at gmail dot com
Description:
------------
There are situations where one want to iterate a list backwards, I was recently in such a situation,
writing:
<?php
$removeWhitespaceTextNodes = function (\DOMNode $node) use (&$removeWhitespaceTextNodes): void {
if ($node->hasChildNodes()) {
// Warning: it's important to do it backwards; if you do it forwards, the index for
DOMNodeList might become invalidated;
// that's why i don't use ForEach() - don't change it (unless you know what
you're doing, ofc)
for ($i = $node->childNodes->length - 1; $i >= 0; --$i) {
$removeWhitespaceTextNodes($node->childNodes->item($i));
}
}
if ($node->nodeType === XML_TEXT_NODE && !$node->hasChildNodes() &&
!$node->hasAttributes() && (strlen(trim($node->textContent)) === 0)) {
$node->parentNode->removeChild($node);
}
};
?>
I think it could be useful if ForEach() could iterate stuff backwards, maybe something like:
<?php
ForEach($iterable as $index=>$val, $flags = 0){}
?>
(with a new FOREACH_BACKWARDS flag)
or maybe just
<?php
ForEach($iterable as $index=>$val, bool $backwards = false){}
?>
or something like that?
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=80120&edit=1