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 02:00] – amenthes | rfc:iteration-tools [2008/11/03 14:57] – changed status and date amenthes | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== Request for Comments: Iteration tools in PHP ====== | ====== Request for Comments: Iteration tools in PHP ====== | ||
* 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 ===== | ||
- | Most of the programs we write, invariable of the programming language we use, have as their purpose data processing. While this data can be represented in various formats it is as true that quite often this data comes grouped as sets of data. For example it is a common situation to issue a database query which resturns | + | Most of the programs we write, invariable of the programming language we use, have as their purpose data processing. While this data can be represented in various formats it is as true that quite often this data comes grouped as sets of data. For example it is a common situation to issue a database query which returns |
* array. Ex: scandir() | * array. Ex: scandir() | ||
* Traversable. Ex: DirectoryIterator | * Traversable. Ex: DirectoryIterator | ||
Line 21: | Line 21: | ||
* foreach | * foreach | ||
- | Given that this is such a recurrent situation | + | 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' |
- | ==== Why do we need RFCs? ==== | ||
- | 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' | + | ==== Why do we need tools for iteration ==== |
+ | |||
+ | Given that iteration is such a recurrent situation and conforming to the DRY principle, but also in total respect with common sense, an abstraction is required. Thankfully, patterns | ||
For example: | For example: | ||
* some of the functions modify data in the set | * some of the functions modify data in the set | ||
Line 32: | Line 33: | ||
* some use all the data in the result to create a combined result | * some use all the data in the result to create a combined result | ||
- | ...and 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 | ||
* FilterIterator | * FilterIterator | ||
* RecursiveFilterIterator | * RecursiveFilterIterator | ||
Line 39: | Line 41: | ||
* SearchIterator | * SearchIterator | ||
+ | ====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 | + | * They only iterate over Traversables. Supporting arrays would be nice (Indeed, we have array_map(), |
* FilterIterator, | * FilterIterator, | ||
- | * Although not a shortcoming, we need a few more abstraction | + | * CallbackFilterIterator, although I haven' |
- | What I'm proposing is introduction | + | What I'm proposing is introducing |
- | * map | + | * map() |
- | * forEach | + | * walk() - this is forEach() in JavaScript |
- | * reduce (an alternative name in some languages is fold) | + | * reduce() - in some languages |
- | * reduceRight (an alternative name in some languages is foldr) | + | * reduceRight() - in some languages |
- | * filter | + | * filter() |
- | * some | + | * some() |
- | * every | + | * every() |
- | Pages in the Mozilla Developer Center wiki documenting these functions can be found here: | + | ===== Common Misconceptions ===== |
+ | |||
+ | None that I know of yet. | ||
+ | |||
+ | ===== Proposal and Patch ===== | ||
+ | |||
+ | |||
+ | Pages from Mozilla Developer Center wiki documenting these kind of functions can be found here: | ||
* https:// | * https:// | ||
* https:// | * https:// | ||
- | Some documentation about these functions, most of it pasted from MDC modified where necessary because of PHP related aspects: | + | Some PHP function signatures, mostly identical to the JavaScript versions, modified where necessary because of PHP related aspects: |
===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) | ||
- | ===forEach()=== | + | ===walk()=== |
- | * Signature: void forEach(array|Traversable iter, callback callback) | + | * This is named forEach() inside JavaScript but that's not possible inside PHP. Anyway, we already have an array_walk() function so this name might be actually a good choice |
+ | * Signature: void walk(array|Traversable iter, callback callback) | ||
* Description: | * Description: | ||
* Callback signature: void callback(mixed value, mixed key, array|Traversable iter) | * Callback signature: void callback(mixed value, mixed key, array|Traversable iter) | ||
+ | |||
+ | ===walkRecursive()=== | ||
+ | * Should there be such a function? | ||
===reduce()=== | ===reduce()=== | ||
Line 78: | Line 91: | ||
===reduceRight()=== | ===reduceRight()=== | ||
- | Same as reduce() but in reverse. | + | |
===filter()=== | ===filter()=== | ||
Line 95: | 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 functions could do just fine because of the new namespace support that's why I represented them as such. | ||
+ | Additionally, | ||
==== Use cases ==== | ==== Use cases ==== | ||
- | + | This an example PHP script for reading | |
- | This an example | + | |
<code php> | <code php> | ||
<?php | <?php | ||
- | // 1.1 how could be done right now ------------------------------------------------- | + | // 1.1 How it could be done right now ------------------------------------------------- |
class OnlyPHPFiles extends FilterIterator { | class OnlyPHPFiles extends FilterIterator { | ||
public function accept() { | public function accept() { | ||
Line 117: | Line 131: | ||
} | } | ||
- | // 1.2 or with the CallbackFilterIterator which I don't know with which PHP | + | // 1.2 Using CallbackFilterIterator which I don't know with which PHP |
// version it will be shipped | // version it will be shipped | ||
$dirs = new CallbackFilterIterator(new DirectoryIterator(__DIR__), | $dirs = new CallbackFilterIterator(new DirectoryIterator(__DIR__), | ||
Line 125: | Line 139: | ||
- | // 2.1 how could be done right now with my proposal ------------------------------------ | + | // 2.1 How it could be done with my proposal |
$dirs = filter(new DirectoryIterator(__DIR__), | $dirs = filter(new DirectoryIterator(__DIR__), | ||
$ext = strtolower(pathinfo($this-> | $ext = strtolower(pathinfo($this-> | ||
Line 131: | Line 145: | ||
}); | }); | ||
- | ?> | ||
</ | </ | ||
- | 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. | + | 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 |
+ | =====Some aditional benefits===== | ||
+ | As you have seen, my proposal includes a function called walk() which does exactly the same thing as a foreach construct. The real useful thing this function provides is the ability to mimic scope inside a foreach block. So, for example: | ||
+ | <code php> | ||
+ | foreach ($iter as $elem) { | ||
+ | // everything inside this foreach block is in the global space | ||
+ | } | ||
+ | // whereas | ||
+ | $global_var = ' | ||
- | ===== Common Misconceptions ===== | + | walk($iter, function($elem) use ($global_var) { |
+ | // this is not the global space | ||
+ | // but we may still use variables from the global space | ||
+ | // by " | ||
+ | }); | ||
- | RFCs do not in any way replace discussions on the mailing list. | + | </ |
- | ===== Proposal and Patch ===== | + | It would have been an advantage if our lambdas had been self-executing, |
- | Nothing needs to be patched here. Just use this template at your discretion. | + | <code php> |
+ | // as far as I know this doesn' | ||
+ | foreach ($iter as $elem) { | ||
+ | (function($elem) | ||
+ | // not global scope | ||
+ | })(); | ||
+ | } | ||
+ | </ | ||
- | ==== Rejected Features ==== | + | ===== Rejected Features |
- | Automated voting system. | + | None for the moment |
+ | |||
+ | ===== Similar implementations ===== | ||
+ | |||
+ | JavaScript 1.8: | ||
+ | * https:// | ||
+ | * https:// | ||
- | ==== More about RFCs ==== | + | Python: |
+ | * http:// | ||
+ | * http:// | ||
- | http:// | ||
===== Changelog ===== | ===== Changelog ===== |
rfc/iteration-tools.txt · Last modified: 2017/09/22 13:28 by 127.0.0.1