php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #80120 ForEach() backwards support?
Submitted: 2020-09-18 08:33 UTC Modified: 2020-09-18 19:59 UTC
From: divinity76 at gmail dot com Assigned:
Status: Not a bug Package: *General Issues
PHP Version: Next Minor Version OS:
Private report: No CVE-ID: None
 [2020-09-18 08:33 UTC] 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?


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-09-18 16:20 UTC] requinix@php.net
-Status: Open +Status: Feedback
 [2020-09-18 16:20 UTC] 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 17:19 UTC] 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 19:59 UTC] requinix@php.net
-Status: Feedback +Status: Not a bug
 [2020-09-18 19:59 UTC] requinix@php.net
> 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?)
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 21:01:36 2024 UTC