Re: List comprehensions and generator expressions for PHP
| From: | Sebastian Krebs | Date: | Thu, 28 Jun 2012 13:45:54 +0000 |
| Subject: | Re: List comprehensions and generator expressions for PHP | ||
| References: | 1 2 3 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-61026@lists.php.net to get a copy of this message | ||
Hi,
2012/6/28 David Muir <davidkmuir@gmail.com>
> I'd assume that array_map() only works with arrays, while list
> comprehension should work with anything traversable.
>
That sounds more like a "bug" (better: "Missing feature") in array_map()
and less a missing language feature...
Regards,
Sebastian
>
> 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
> >>
> >>
>