====== Straw poll: Naming for *any() and *all() on iterables ====== * Version: 0.2 * Date: 2020-12-19 * Author: Tyson Andre, tandre@php.net * Status: Complete * First Published at: http://wiki.php.net/rfc/any_all_on_iterable_straw_poll ===== Introduction ===== The primitives ''any()'' and ''all()'' are a common part of many programming languages and help in avoiding verbosity or unnecessary abstractions. - Haskell: https://hackage.haskell.org/package/base-4.14.0.0/docs/Prelude.html#v:any - JavaScript: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some - Python: https://docs.python.org/3/library/functions.html#all - Ruby: https://apidock.com/ruby/Enumerable/any%3F - Java 8(Stream): https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#allMatch-java.util.function.Predicate- - C++: https://www.cplusplus.com/reference/algorithm/any_of/ 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. - It reduces the chance of conflicting with functions in existing codebases. - It makes it easier to look up and remember the name of related functionality. - 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.
/** 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, [[https://www.php.net/manual/en/class.iterator|Iterator]] and [[https://www.php.net/manual/en/class.iteratoraggregate.php|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 =====
- https://wiki.php.net/rfc/any_all_on_iterable
- https://github.com/php/php-src/pull/6053
===== Changelog =====
0.2: Document why ''iterator_'' was not considered as an option.