rfc:any_all_on_iterable_straw_poll

This is an old revision of the document!


Straw poll: Naming for *any() and *all() on iterables

Introduction

The primitives any() and all() are a common part of many programming languages and help in avoiding verbosity or unnecessary abstractions.

Before adding this, I'd like to see what others think about the choice of naming pattern. I don't find adding a prefix visibly appealing, but the argument for the need for a prefix makes sense to me if php were to add functions such as iterable_reduce(), iterable_count(array|Traversable|Countable), iterable_take(iterable, int $limit), etc.

  1. It reduces the chance of conflicting with functions in existing codebases.
  2. It makes it easier to look up and remember the name of related functionality.
  3. Some other languages have ways to import modules (instead of a shared global namespace like php), or put functionality inside of methods instead of global functions, or compile code ensuring only one language version needs to be supported. (Python is a counterexample, where the global function any() is available by default).

https://externals.io/message/111756#111814

The main thing I'm concerned about is that once we start extending this area (I assume that any & all are not going to be the last additions in this space) we will quickly run into function names that are either too generic or outright collide. For example, what if we want to add an iterator-based version of range()? Do we really want to be forced to pull a Python and call it xrange()? That's about as good as real_range()...

As such, I think it's important to prefix these somehow, though I don't care strongly how. Could be iter_all() or iterable_all(). We might even make it iterator_all() if we also adjust other existing iterator_* functions to accept iterables. I'd also be happy with iter\all() or iterable\all(), but that gets us back into namespacing discussions :)

Regards, Nikita

Vote

This vote will influence the name choice for the RFC https://wiki.php.net/rfc/any_all_on_iterable

Voting starts on 2020-12-19 and will close on 2020-12-26.

Straw poll: Preferred choice of naming pattern
Real name any() and all() iter_any() and iter_all() iterable_any() and iterable_all() Opposed to names Opposed to adding this functionality
asgrim (asgrim)     
ashnazg (ashnazg)     
beberlei (beberlei)    
bmajdak (bmajdak)     
colinodell (colinodell)     
crell (crell)   
duncan3dc (duncan3dc)     
galvao (galvao)     
kelunik (kelunik)    
levim (levim)     
mariano (mariano)    
mauricio (mauricio)    
nikic (nikic)    
ocramius (ocramius)    
patrickallaert (patrickallaert)     
pollita (pollita)    
ramsey (ramsey)     
reinders (reinders)     
sergey (sergey)     
tandre (tandre)     
Count: 3 6 16 4 0

What the functions do

See https://wiki.php.net/rfc/any_all_on_iterable

/** Determines whether any element of the iterable satisfies the predicate. */
function(iterable $input, ?callable $callback = null) {
    foreach ($input as $v) {
        if ($callback !== null ? $callback($v) : $v) {
            return true;
        }
    }
    return false;
}
 
/** Determines whether all elements of the iterable satisfy the predicate */
function(iterable $input, ?callable $callback = null) {
    foreach ($input as $v) {
        if (!($callback !== null ? $callback($v) : $v)) {
            return false;
        }
    }
    return true;
}

Rejected Choices

Namespaces such as iter\any() were not considered because existing core global functions are already in the global namespace, and recent suggestions for adopting namespaces for internal functionality have been unpopular (https://wiki.php.net/rfc/php_namespace_policy)

Using static methods instead of global functions was not considered since it would be impractical to polyfill new functions that get added in future php versions in a standard way. (e.g. IterUtils::all())

Existing iterator methods

The prefix iterator_ was not considered. In PHP, Iterator and IteratorAggregate already exist, and classes that implement Traversable must implement either Iterator or IteratorAggregate. The name iterator_ would be misleading for functions that also accept arrays.

  • I don't want to be in a situation where there are a large number of iterator_*() functions, where some accept Traversable and some accept iterable.
  • I also don't want to be in a situation where some have $iterator as a named argument (since PHP 8.0, e.g. iterator_to_array()) and others have $iterable.
  • If I was choosing names from scratch, *foo(iterable $iterable, ...) would make more sense than iterator_foo(iterable $iterator)

Changing other iterator functions such as iterator_apply(), iterator_count(), and iterator_to_array() to accept iterator instead of Traversable(Iterator and IteratorAggregate) is out of the scope of the RFC or straw poll.

  • My preference would be to add new iterable_apply(), iterable_count(), and iterable_to_array() functions instead of modifying the existing methods. This would be possible to polyfill, and it would be less likely that code developed for 8.1+ would pass arrays that would be rejected by php 8.0 and older.
  • Any alternative RFCs to change the behaviors of iterator_apply(), iterator_count(), and iterator_to_array() can be done independently of adding *any() and *all().

References

Changelog

0.2: Document why iterator_ was not considered as an option.

rfc/any_all_on_iterable_straw_poll.1608479147.txt.gz · Last modified: 2020/12/20 15:45 by tandre