rfc:iteration-tools
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
rfc:iteration-tools [2008/10/29 21:46] – corrected big, big logical mistake amenthes | rfc:iteration-tools [2008/11/03 15:03] – amenthes | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Request for Comments: | + | ====== Request for Comments: |
* Version: 1.0 | * Version: 1.0 | ||
- | * Date: 2008-10-29 | + | * Date: 2008-11-03 |
* Author: Ionut Gabriel Stan < | * Author: Ionut Gabriel Stan < | ||
- | * Status: | + | * Status: |
- | * First Published at: http:// | + | * First Published at: http:// |
This RFC proposes a series of functions or classes | This RFC proposes a series of functions or classes | ||
- | to facilitate easy processing of data sets represented as either arrays or Traversables. The assumed PHP version is 5.3 because of the new lambda structures | + | to facilitate easy processing of data sets represented as either arrays or Traversables. The assumed PHP version is 5.3 because of the new lambda structures |
===== Introduction ===== | ===== Introduction ===== | ||
Line 21: | Line 21: | ||
* foreach | * foreach | ||
- | Depending on the task at hand the processing involved inside these loops may be ridiculously easy or painfully hard. With time, the more you do this the more you realize there' | + | Depending on the task at hand the processing involved inside these loops may be ridiculously easy or painfully hard. With time, the more you do this the more you realize there' |
Line 27: | Line 27: | ||
==== Why do we need tools for iteration ==== | ==== Why do we need tools for iteration ==== | ||
- | Given that this is such a recurrent situation and conforming to the DRY principle but also in total respect with common sense an abstraction is required. Thankfully, | + | Given that iteration |
For example: | For example: | ||
* some of the functions modify data in the set | * some of the functions modify data in the set | ||
Line 34: | Line 34: | ||
The list may go on with a few other abstracted use cases. | The list may go on with a few other abstracted use cases. | ||
- | It turns out that separating the iteration from the inner data calculations is a good thing and people came up with what they called | + | |
+ | It turns out that separating the iteration from the inner data calculations is a good thing and people came up with some higher order functions, that took at least two parameters, the data set to be processed and the *function* that did the processing (which in some of the cases were " | ||
* FilterIterator | * FilterIterator | ||
* RecursiveFilterIterator | * RecursiveFilterIterator | ||
Line 42: | Line 43: | ||
====Shortcomings of current tools==== | ====Shortcomings of current tools==== | ||
While these classes do their job they have some shortcomings: | While these classes do their job they have some shortcomings: | ||
- | * They only iterate over Traversables. Supporting arrays would be nice (Indeed, we have array_map(), | + | * They only iterate over Traversables. Supporting arrays would be nice (Indeed, we have array_map(), |
* FilterIterator, | * FilterIterator, | ||
- | * Although not a shortcoming, | ||
* CallbackFilterIterator, | * CallbackFilterIterator, | ||
- | What I'm proposing is introducing in the language of the following functions, which are similar to those existing | + | What I'm proposing is introducing in the language of the following functions, which are similar to the Array methods that exist in JavaScript 1.8: |
* map() | * map() | ||
- | * forEach() | + | * walk() - this is forEach() |
- | * reduce() | + | * reduce() - in some languages |
- | * reduceRight() - an alternative name in some languages | + | * reduceRight() - in some languages |
* filter() | * filter() | ||
* some() | * some() | ||
* every() | * every() | ||
- | |||
- | |||
- | ==== Use cases ==== | ||
- | This an example PHP script for reading files with .php extension from a certain directory. | ||
- | |||
- | <code php> | ||
- | <?php | ||
- | |||
- | // 1.1 how could it be done right now ------------------------------------------------- | ||
- | class OnlyPHPFiles extends FilterIterator { | ||
- | public function accept() { | ||
- | $ext = strtolower(pathinfo($this-> | ||
- | return $ext === ' | ||
- | } | ||
- | } | ||
- | |||
- | $dirs = array(); | ||
- | foreach (new OnlyPHPFiles(new DirectoryIterator(__DIR__)) as $file) { | ||
- | $dirs[] = $file; | ||
- | } | ||
- | |||
- | // 1.2 or with the CallbackFilterIterator which I don't know with which PHP | ||
- | // version it will be shipped | ||
- | $dirs = new CallbackFilterIterator(new DirectoryIterator(__DIR__), | ||
- | $ext = strtolower(pathinfo($this-> | ||
- | return $ext === ' | ||
- | }); | ||
- | |||
- | |||
- | // 2.1 how could be done with my proposal -------------------------------------- | ||
- | $dirs = filter(new DirectoryIterator(__DIR__), | ||
- | $ext = strtolower(pathinfo($this-> | ||
- | return $ext === ' | ||
- | }); | ||
- | |||
- | </ | ||
- | |||
- | While the 1.2 example is very similar to 2.1 it differs from it in that it's not passing the iterator to the callback function. Another difference is that CallbackFilterIterator may also be used as a virtual CallbackMapIterator. For example, it's not only filtering the elements of the iterator into a new iterator, but it MAY also change those values. In my proposal, the function that changes values is map() which translates a certain value to another depending on the callback function. filter() only keeps items that validate agains certain criteria inside the callback function. | ||
- | |||
- | |||
===== Common Misconceptions ===== | ===== Common Misconceptions ===== | ||
- | RFCs do not in any way replace discussions on the mailing list. | + | None that I know of yet. |
===== Proposal and Patch ===== | ===== Proposal and Patch ===== | ||
+ | |||
Pages from Mozilla Developer Center wiki documenting these kind of functions can be found here: | Pages from Mozilla Developer Center wiki documenting these kind of functions can be found here: | ||
Line 110: | Line 71: | ||
===map()=== | ===map()=== | ||
* Signature: array|Iterator map(array|Traversable iter, callback callback) | * Signature: array|Iterator map(array|Traversable iter, callback callback) | ||
- | * Description: | + | * Description: |
* Callback signature: mixed callback(mixed value, mixed key, array|Traversable iter) | * Callback signature: mixed callback(mixed value, mixed key, array|Traversable iter) | ||
- | |||
===walk()=== | ===walk()=== | ||
Line 120: | Line 80: | ||
* Callback signature: void callback(mixed value, mixed key, array|Traversable iter) | * Callback signature: void callback(mixed value, mixed key, array|Traversable iter) | ||
- | + | ===walkRecursive()=== | |
- | ====walkRecursive()=== | + | |
* Should there be such a function? | * Should there be such a function? | ||
- | |||
===reduce()=== | ===reduce()=== | ||
Line 150: | Line 108: | ||
* Callback signature: bool callback(mixed value, mixed key, array|Traversable iter) | * Callback signature: bool callback(mixed value, mixed key, array|Traversable iter) | ||
- | Although the above tools were listed as functions, as they don't do that much, they might just as well be class constructors (honestly I don't like this approach). I thought | + | Although the above tools were listed as functions, as they don't do that much, they might just as well be class constructors (honestly I don't like this approach). I thought functions |
+ | Additionally, | ||
+ | |||
+ | ==== Use cases ==== | ||
+ | This an example PHP script for reading files with .php extension from a certain directory. | ||
+ | |||
+ | <code php> | ||
+ | <?php | ||
+ | |||
+ | // 1.1 How it could be done right now ------------------------------------------------- | ||
+ | class OnlyPHPFiles extends FilterIterator { | ||
+ | public function accept() { | ||
+ | $ext = strtolower(pathinfo($this-> | ||
+ | return $ext === ' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | $dirs = array(); | ||
+ | foreach (new OnlyPHPFiles(new DirectoryIterator(__DIR__)) as $file) { | ||
+ | $dirs[] = $file; | ||
+ | } | ||
+ | |||
+ | // 1.2 Using CallbackFilterIterator which I don't know with which PHP | ||
+ | // version it will be shipped | ||
+ | $dirs = new CallbackFilterIterator(new DirectoryIterator(__DIR__), | ||
+ | $ext = strtolower(pathinfo($this-> | ||
+ | return $ext === ' | ||
+ | }); | ||
+ | |||
+ | |||
+ | // 2.1 How it could be done with my proposal -------------------------------------- | ||
+ | $dirs = filter(new DirectoryIterator(__DIR__), | ||
+ | $ext = strtolower(pathinfo($this-> | ||
+ | return $ext === ' | ||
+ | }); | ||
+ | |||
+ | </ | ||
+ | |||
+ | While the 1.2 example is very similar to 2.1 it differs from it in that it's not passing the iterator to the callback function and, of course, the fact that I use a function instead of an object. Another difference is that present implementation of CallbackFilterIterator (as documented on http:// | ||
=====Some aditional benefits===== | =====Some aditional benefits===== | ||
Line 158: | Line 154: | ||
<code php> | <code php> | ||
foreach ($iter as $elem) { | foreach ($iter as $elem) { | ||
- | // everything inside this foreach block | + | // everything inside this foreach block is in the global space |
- | // is in the global space | + | |
} | } | ||
Line 174: | Line 169: | ||
</ | </ | ||
- | It wouldn' | + | It would have been an advantage if our lambdas had been self-executing, |
<code php> | <code php> | ||
Line 185: | Line 180: | ||
</ | </ | ||
- | ==== Rejected Features ==== | + | ===== Rejected Features |
- | To be completed | + | None for the moment |
- | ==== Similar implementations ==== | + | ===== Similar implementations |
JavaScript 1.8: | JavaScript 1.8: | ||
Line 197: | Line 192: | ||
Python: | Python: | ||
* http:// | * http:// | ||
- | * http:// | + | * http:// |
- | + | ||
- | + | ||
- | ===== Changelog ===== | + | |
- | + | ||
- | + | ||
rfc/iteration-tools.txt · Last modified: 2017/09/22 13:28 by 127.0.0.1