rfc:any_all_on_iterable

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Last revisionBoth sides next revision
rfc:any_all_on_iterable [2021/02/06 14:42] tandrerfc:any_all_on_iterable [2021/02/22 15:28] tandre
Line 1: Line 1:
 ====== PHP RFC: PHP\iterable\any() and all() on iterables ====== ====== PHP RFC: PHP\iterable\any() and all() on iterables ======
-  * Version: 0.4+  * Version: 0.6
   * Date: 2020-08-30   * Date: 2020-08-30
   * Author: Tyson Andre, tandre@php.net   * Author: Tyson Andre, tandre@php.net
-  * Status: Under Discussion+  * Status: Declined
   * First Published at: https://wiki.php.net/rfc/any_all_on_iterable   * First Published at: https://wiki.php.net/rfc/any_all_on_iterable
   * Implementation: https://github.com/php/php-src/pull/6053   * Implementation: https://github.com/php/php-src/pull/6053
Line 49: Line 49:
 ===== Proposal ===== ===== Proposal =====
  
-Add the functions ''PHP\iterable\any(iterable $input, ?callable $callback = null): bool'' and ''all(...)'' to PHP's standard function set.+Add the functions ''PHP\iterable\any(iterable $input, ?callable $callback = null): bool'' and ''all(...)'' to PHP's standard library'function set.
 (The namespace ''PHP\iterable'' was preferred in [[rfc:any_all_on_iterable_straw_poll_namespace#vote|a straw poll that was previously sent out]]) (The namespace ''PHP\iterable'' was preferred in [[rfc:any_all_on_iterable_straw_poll_namespace#vote|a straw poll that was previously sent out]])
 +
 +**The implementation is equivalent to the following polyfill:**
  
 <code php> <code php>
 namespace PHP\iterable; namespace PHP\iterable;
  
-/** Determines whether any element of the iterable satisfies the predicate. */ +/*
-function any(iterable $input, ?callable $callback = null) {+ * Determines whether any element of the iterable satisfies the predicate. 
 + * 
 + * 
 + * If the value returned by the callback is truthy 
 + * (e.g. true, non-zero number, non-empty array, truthy object, etc.), 
 + * this is treated as satisfying the predicate. 
 + * 
 + * @param iterable $input 
 + * @param null|callable(mixed):mixed $callback 
 + */ 
 +function any(iterable $input, ?callable $callback = null): bool {
     foreach ($input as $v) {     foreach ($input as $v) {
         if ($callback !== null ? $callback($v) : $v) {         if ($callback !== null ? $callback($v) : $v) {
Line 64: Line 76:
     return false;     return false;
 } }
-/** Determines whether all elements of the iterable satisfy the predicate */ +</code> 
-function all(iterable $input, ?callable $callback = null) {+<code php> 
 +/*
 + * Determines whether all elements of the iterable satisfy the predicate
 + * 
 + * If the value returned by the callback is truthy 
 + * (e.g. true, non-zero number, non-empty array, truthy object, etc.), 
 + * this is treated as satisfying the predicate. 
 + * 
 + * @param iterable $input 
 + * @param null|callable(mixed):mixed $callback 
 + */ 
 +function all(iterable $input, ?callable $callback = null): bool {
     foreach ($input as $v) {     foreach ($input as $v) {
         if (!($callback !== null ? $callback($v) : $v)) {         if (!($callback !== null ? $callback($v) : $v)) {
Line 80: Line 103:
   - If this was provided only in userland, there'd be low adoption and code such as the above example (API::somePredicate()) would remain common.   - If this was provided only in userland, there'd be low adoption and code such as the above example (API::somePredicate()) would remain common.
   - If the standard library provided it, then polyfills for newer php functionality could adopt this as well, making cleaner code easier to write.   - If the standard library provided it, then polyfills for newer php functionality could adopt this as well, making cleaner code easier to write.
 +
 +==== Implementation Details ====
 +
 +When ''any()'' or ''all()'' are called with an iterable and a predicate, it internally checks if the value returned by the predicate is truthy (e.g. true, non-zero numbers, non-empty arrays, truthy objects, etc.)
 +
 +When ''any()'' or ''all()'' are called with only an iterable, it is equivalent to checking if any/all of the arguments are truthy. This is equivalent to calling ''any()''/''all()'' with ''fn ($x) => $x'', which is equivalent to calling it with ''fn($x) => (bool)$x''.
 +
 +
 +<code php>
 +php > var_export(PHP\iterable\any([false]));
 +false
 +php > var_export(PHP\iterable\any([true]));
 +true
 +php > var_export(PHP\iterable\any([0]));
 +false
 +php > var_export(PHP\iterable\any([1]));
 +true
 +php > var_export(PHP\iterable\any([0], fn($x) => $x));
 +false
 +php > var_export(PHP\iterable\any([1], fn($x) => $x));
 +true
 +
 +php > var_export(PHP\iterable\all([true, true, true], fn($x) => $x));
 +true
 +php > var_export(PHP\iterable\all([1, 2, 3], fn($x) => $x));
 +true
 +php > var_export(PHP\iterable\all([true, true, false], fn($x) => $x));
 +false
 +php > var_export(PHP\iterable\all([1, 2, 0], fn($x) => $x));
 +false
 +php > var_export(PHP\iterable\all([1, 2, 0]);
 +false
 +</code>
  
 ==== Secondary Vote: any()/all() or any_value()/all_values() ==== ==== Secondary Vote: any()/all() or any_value()/all_values() ====
Line 103: Line 159:
 Benefits of a shorter name: Benefits of a shorter name:
  
-  - Conciseness for the most common use of ''any*'' and ''all*'' +  - Conciseness for the most common use case of checking whether a predicate is true for any/all values of an iterable array/object. 
-  - Consistency with some other functions such as ''array_reduce()'', ''in_array()'', ''next()'' that act only on values+  - Consistency with some other functions such as ''array_reduce()'', ''array_unique()'', ''in_array()'', ''next()'' that use values for their underlying implementation (i.e. not being named ''array_reduce_values()'', ''next_value()'', etc.)
   - Potential to use $flags to extend this to support less common use cases like ''ARRAY_FILTER_USE_KEY''/''ARRAY_FILTER_USE_BOTH'' without adding more global functions   - Potential to use $flags to extend this to support less common use cases like ''ARRAY_FILTER_USE_KEY''/''ARRAY_FILTER_USE_BOTH'' without adding more global functions
  
 Benefits of a longer name: Benefits of a longer name:
  
-  - Descriptiveness/harder to misread+  - A longer name would be more descriptive and make it easier to understand what code is doing
-  - More likely to add multiple functions such as ''any_key()''/(''any_entry'' or ''any_key_value''in the future (which will be simpler to statically analyze or infer types for - in rare cases the argument $flags passed to ''array_filter($values, $callback, $flags)'' is an unknown dynamic value). \\ Note that adding the name ''any()'' for values of iterables doesn't prevent PHP from adding ''any_key()'' for checking keys of iterables in the future, either.+  - This makes it likely that in the future for iterable functionality, PHP will add multiple functions such as ''any_key()''/(''any_entry'' or ''any_key_value''instead of using $flags (which will be simpler to statically analyze or infer types for - in rare cases the argument $flags passed to ''array_filter($values, $callback, $flags)'' is an unknown dynamic value). \\ Adding a constant such as ''flags: PHP\iterable\USE_KEY'' may make the code longer. \\ Note that adding the name ''any()'' for values of iterables doesn't prevent PHP from adding ''any_key()'' for checking keys of iterables in the future, either (my personal preference would be to add ''any_key()'' regardless of whether ''any()''/''any_value()'' was added).
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
Line 233: Line 289:
  
  
-===== Proposed Voting Choices =====+===== Vote ===== 
 + 
 +Add ''PHP\iterable\any(iterable $input, ?callable $callback = null): bool'' and ''PHP\iterable\all(iterable $input, ?callable $callback = null): bool'' (yes/no, requiring a 2/3 majority) 
 + 
 +Voting started on 2021-02-08 and ended on 2021-02-22. 
 + 
 +<doodle title="Add PHP\iterable\any() and all() to PHP?" voteType="single" auth="tandre" closed="true"> 
 +   * Yes 
 +   * No 
 +</doodle> 
 + 
 + \\ The following secondary vote will be used to decide between ''any()''/''all()'' and ''any_value()''/''all_values()'' as the name within the ''PHP\iterable'' namespace. See [[#secondary_voteanyall_or_any_valueall_values|the discussion section for the benefits/drawbacks of those names]]. 
 + 
 +<doodle title="Names to use: any()/all() or any_value()/all_values()" voteType="single" auth="tandre" closed="false"> 
 +   * any()/all() 
 +   * any_value()/all_values() 
 +</doodle>
  
-Add ''PHP\iterable\any(iterable $input, ?callable $callback null)'' and ''PHP\iterable\all(...)'' (yes/no, requiring 2/3 majority)+==== Straw Poll ====
  
-A secondary vote requiring a simple majority will be used to decide between ''any()''/''all()'' and ''any_value()''/''all_values()'' as the name within the ''PHP\iterable'' namespace. See [[#secondary_voteanyall_or_any_valueall_values|the discussion section for the benefits/drawbacks of those names]].+<doodle title="Reasons for voting against this RFC" voteType="multi" auth="tandre" closed="false"> 
 +   * Too small in scope 
 +   * Object to the choice of namespace 
 +   * Prefer the global namespace 
 +   * Confused about the implementation 
 +   * Prefer userland solutions 
 +   * Other 
 +   * Voted for this RFC 
 +</doodle>
  
 ===== References ===== ===== References =====
Line 255: Line 335:
   * 0.3: Add more quotes   * 0.3: Add more quotes
   * 0.4: Change name to ''PHP\iterable\all'' and ''PHP\iterable\any'', add a secondary vote on ''any/all'' vs ''any_value()/all_values()''   * 0.4: Change name to ''PHP\iterable\all'' and ''PHP\iterable\any'', add a secondary vote on ''any/all'' vs ''any_value()/all_values()''
 +  * 0.5: Add straw poll
 +  * 0.6: Add examples of how this works, add in missing return type, clarify treatment of predicate $callback return type
rfc/any_all_on_iterable.txt · Last modified: 2021/06/13 14:36 by tandre