Re: List comprehensions and generator expressions for PHP
| From: | David Muir | Date: | Thu, 28 Jun 2012 13:22:31 +0000 |
| Subject: | Re: List comprehensions and generator expressions for PHP | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-61024@lists.php.net to get a copy of this message | ||
I'd assume that array_map() only works with arrays, while list comprehension should work with
anything traversable.
David
On 28/06/2012, at 10:43 PM, Sebastian Krebs <krebs.seb@gmail.com> wrote:
> Hi,
>
> Whats the difference to the (already existing) function array_map() (except
> the syntax and one more new keyword)?
>
>> $firstNames = array_map(function($user){return $user->firstname;},
> $users);
>
> Don't want to rewrite every example you gave, but you probably see my point.
>
> Regards,
> Sebastian
>
> 2012/6/28 Nikita Popov <nikita.ppv@gmail.com>
>
>> Hi internals!
>>
>> Python and several other languages include support for list
>> comprehensions and generator expressions and I'd like to see something
>> similar in PHP too.
>>
>> I created a hacky proof of concept implementation here:
>>
>> https://github.com/nikic/php-src/tree/addListComprehensions.
>> It's
>> really dirty, but it implements both features in about ~150 lines of
>> code.
>>
>> Currently I'm using the following syntax:
>>
>> $firstNames = [foreach ($users as $user) yield $user->firstName];
>>
>> This code is roughly equivalent to writing:
>>
>> $firstNames = [];
>> foreach ($users as $user) {
>> $firstNames[] = $user->firstName;
>> }
>>
>> You may notice that this particular list comprehension provides the
>> same functionality as array_column(), just in a little more
>> generalized way. E.g. you could use all of the following without
>> having special functions for them all:
>>
>> $firstNames = [foreach ($users as $user) yield $user->firstName];
>>
>> $firstNames = [foreach ($users as $user) yield $user->getFirstName()];
>>
>> $firstNames = [foreach ($users as $user) yield $user['firstName']];
>>
>> It's also possible to explicitly specify a key:
>>
>> $firstNames = [foreach ($users as $user) yield $user->id =>
>> $user->firstName];
>>
>> It is also possible to filter elements using list comprehensions:
>>
>> $underageUsers = [foreach ($users as $user) if ($user->age < 18)
>> yield $user];
>> // or just the names
>> $underageUserNames = [foreach ($users as $user) if ($user->age <
>> 18) yield $user->firstName];
>>
>> It is also possible to nest multiple foreach loops:
>>
>> $aList = ['A', 'B'];
>> $bList = [1, 2];
>> $combinations = [foreach ($aList as $a) foreach ($bList as $b)
>> yield [$a, $b]];
>> // gives: [ ['A', 1], ['A', 2], ['B', 1], ['B',
>> 2] ]
>>
>> All the above are list comprehensions (or in PHP rather array
>> comprehensions), i.e. they create an array as the result.
>>
>> If this is not needed it is also possible to compute the values lazily
>> using generator expressions, which use () instead of [].
>>
>> $firstNames = (foreach ($users as $user) yield $user->firstName);
>>
>> In this case $firstNames will no longer be an array of first names,
>> but instead will be a generator producing first names.
>>
>> This is handy if you only need to iterate the resulting "list" only
>> once as it saves you holding the whole list in memory.
>>
>> Also it allows you to work with infinite lists easily:
>>
>> function *naturalNumbers() {
>> for ($i = 0; ; ++$i) {
>> yield $i;
>> }
>> }
>>
>> // all natural numbers
>> $numbers = naturalNumbers();
>> // only the odd ones
>> $oddNumbers = (foreach ($numbers as $n) if ($n % 2) yield $n);
>> // ...
>>
>> (At this point I wonder whether one should include support for
>> for-loops in list comprehensions. So the naturalNumbers() function
>> could be replaced with (for ($i = 0;; ++$i) yield $i), etc)
>>
>> So, what do you think? Do we want something like this in PHP?
>>
>> Nikita
>>
>> --
>> PHP Internals - PHP Runtime Development Mailing List
>> To unsubscribe, visit: http://www.php.net/unsub.php
>>
>>