Welcome! Log In Create A New Profile

Advanced

[PHP-DEV] Let range() return a generator?

Posted by Sebastian Bergmann 
Sebastian Bergmann
[PHP-DEV] Let range() return a generator?
March 17, 2017 07:00AM
For me,

foreach (range($low, $high) as $i)

is easier to understand than

for ($i = 0; $i <= $high; $i++)

By easier to understand I do not only mean that the beginning of the
loop marked by the foreach/range construct is easier to read. While
reading the body of the loop I can be sure that $i is not unexpectedly
modified, for instance.

Be that as it may, what I would like to propose should be useful for use
cases other than the one (see above) that triggered me thinking about this.

range() returns an array that contains all elements requested. Depending
on the amount of elements, this might not be optimal.

One of the most common usages of generators that I have seen is an
alternative, userland implementation of the range() function:

function xrange($start, $end, $step = 1) {
for ($i = $start; $i <= $end; $i += $step) {
yield $i;
}
}

This makes me wonder: would there be a benefit in changing the
implementation of range() to return a generator instead of an array? And
if so, would this constitute a break in backward compatibility?

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Niklas Keller
Re: [PHP-DEV] Let range() return a generator?
March 17, 2017 07:50AM
>
> For me,
>
> foreach (range($low, $high) as $i)
>
> is easier to understand than
>
> for ($i = 0; $i <= $high; $i++)
>
> By easier to understand I do not only mean that the beginning of the loop
> marked by the foreach/range construct is easier to read. While reading the
> body of the loop I can be sure that $i is not unexpectedly modified, for
> instance.
>
> Be that as it may, what I would like to propose should be useful for use
> cases other than the one (see above) that triggered me thinking about this.
>
> range() returns an array that contains all elements requested. Depending
> on the amount of elements, this might not be optimal.
>
> One of the most common usages of generators that I have seen is an
> alternative, userland implementation of the range() function:
>
> function xrange($start, $end, $step = 1) {
> for ($i = $start; $i <= $end; $i += $step) {
> yield $i;
> }
> }
>
> This makes me wonder: would there be a benefit in changing the
> implementation of range() to return a generator instead of an array? And if
> so, would this constitute a break in backward compatibility?


Yes, that's a BC break. Instead of changing it, there could be a new
function. But as it can be simply built in userland, I don't see much
reason to have it in core.

Regards, Niklas
David Rodrigues
Re: [PHP-DEV] Let range() return a generator?
March 17, 2017 08:10AM
I guess that a lot of PHP functions that could be replaced by a Generator
(basically all array functions like array_values(), array_keys(), etc).
But there are a big question: could it be applied to any case? It will be
faster than just an array? Certainly it will be more memory optimized.

About BC, it really could happen. Currently you could use range() that will
returns an array, then if you use functions like is_array() it will fail to
range() with that change.
One option is mark a Generator acceptable for is_array(), but it generates
another BC, and not make much sense.

The best option is mark it as PHP 8.x BC, simplifying all returned arrays
to a Generator (if it really help on performance).

2017-03-17 3:40 GMT-03:00 Niklas Keller <me@kelunik.com>:

> >
> > For me,
> >
> > foreach (range($low, $high) as $i)
> >
> > is easier to understand than
> >
> > for ($i = 0; $i <= $high; $i++)
> >
> > By easier to understand I do not only mean that the beginning of the loop
> > marked by the foreach/range construct is easier to read. While reading
> the
> > body of the loop I can be sure that $i is not unexpectedly modified, for
> > instance.
> >
> > Be that as it may, what I would like to propose should be useful for use
> > cases other than the one (see above) that triggered me thinking about
> this.
> >
> > range() returns an array that contains all elements requested. Depending
> > on the amount of elements, this might not be optimal.
> >
> > One of the most common usages of generators that I have seen is an
> > alternative, userland implementation of the range() function:
> >
> > function xrange($start, $end, $step = 1) {
> > for ($i = $start; $i <= $end; $i += $step) {
> > yield $i;
> > }
> > }
> >
> > This makes me wonder: would there be a benefit in changing the
> > implementation of range() to return a generator instead of an array? And
> if
> > so, would this constitute a break in backward compatibility?
>
>
> Yes, that's a BC break. Instead of changing it, there could be a new
> function. But as it can be simply built in userland, I don't see much
> reason to have it in core.
>
> Regards, Niklas
>



--
David Rodrigues
Adam Baratz
Re: [PHP-DEV] Let range() return a generator?
March 17, 2017 02:00PM
> Yes, that's a BC break. Instead of changing it, there could be a new
> function. But as it can be simply built in userland, I don't see much
> reason to have it in core.


Whether or not it's in core, the two-pronged approach is what Python does
(range and xrange). Sometimes you want an array and not a generator. That
language is really sympathetic to generator use, but it never forces you to
use them. The core libraries are structured thoughtfully in that regard.

Thanks,
Adam
Sara Golemon
Re: [PHP-DEV] Let range() return a generator?
March 17, 2017 04:50PM
On Fri, Mar 17, 2017 at 1:40 AM, Niklas Keller <me@kelunik.com> wrote:
> Yes, that's a BC break. Instead of changing it, there could be a new
> function. But as it can be simply built in userland, I don't see much
> reason to have it in core.
>
100% agreed. This is a 3 line function and doing it in userland means
you can use it in 5.5 or later.

function range($low, $high) {
for ($i = $low; $i <= $high; ++$i) { yield $i; }
}

-Sara

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Sara Golemon
Re: [PHP-DEV] Let range() return a generator?
March 18, 2017 02:20AM
On Fri, Mar 17, 2017 at 10:46 AM, Sara Golemon <pollita@php.net> wrote:
> On Fri, Mar 17, 2017 at 1:40 AM, Niklas Keller <me@kelunik.com> wrote:
>> Yes, that's a BC break. Instead of changing it, there could be a new
>> function. But as it can be simply built in userland, I don't see much
>> reason to have it in core.
>>
> 100% agreed. This is a 3 line function and doing it in userland means
> you can use it in 5.5 or later.
>
> function range($low, $high) {
> for ($i = $low; $i <= $high; ++$i) { yield $i; }
> }
>
In fact, here: This is how easy that is.

https://packagist.org/packages/phplang/generator

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
David Rodrigues
Re: [PHP-DEV] Let range() return a generator?
March 18, 2017 02:50AM
There are some way to PHP be flagged before run some function, and
understand that you wants to return a Generator instead of array?
For instance: new Generator(range(1, 1000)) makes range() work like a
generator instead of return an array - it's an alternative to avoid new
keywords.
Or, maybe, some side implementation like Generator::range(1, 1000),
Generator::array_values($array), etc. (Currently, for instance, we can
simulate the range() Generator, but not array_values())

2017-03-17 22:14 GMT-03:00 Sara Golemon <pollita@php.net>:

> On Fri, Mar 17, 2017 at 10:46 AM, Sara Golemon <pollita@php.net> wrote:
> > On Fri, Mar 17, 2017 at 1:40 AM, Niklas Keller <me@kelunik.com> wrote:
> >> Yes, that's a BC break. Instead of changing it, there could be a new
> >> function. But as it can be simply built in userland, I don't see much
> >> reason to have it in core.
> >>
> > 100% agreed. This is a 3 line function and doing it in userland means
> > you can use it in 5.5 or later.
> >
> > function range($low, $high) {
> > for ($i = $low; $i <= $high; ++$i) { yield $i; }
> > }
> >
> In fact, here: This is how easy that is.
>
> https://packagist.org/packages/phplang/generator
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


--
David Rodrigues
Sara Golemon
Re: [PHP-DEV] Let range() return a generator?
March 18, 2017 03:00AM
On Fri, Mar 17, 2017 at 8:40 PM, David Rodrigues <david.proweb@gmail.com> wrote:
> There are some way to PHP be flagged before run some function, and
> understand that you wants to return a Generator instead of array?
> For instance: new Generator(range(1, 1000)) makes range() work like a
> generator instead of return an array - it's an alternative to avoid new
> keywords.
> Or, maybe, some side implementation like Generator::range(1, 1000),
> Generator::array_values($array), etc. (Currently, for instance, we can
> simulate the range() Generator, but not array_values())
>
Why would array_values() as a generator be difficult?

function generate_values(Traversable $in) {
foreach ($in as $k => $v) {
yield $k => $v;
}
}

In general, your `new Generator($arr)` concept misses most of the
usefulness of using a generator since arrays are already traversable,
and you've already allocated all the space of a full container.
Where's the benefit from making it a generator?

-Sara

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
David Rodrigues
Re: [PHP-DEV] Let range() return a generator?
March 18, 2017 03:20AM
Yeah, sorry, it was a bad example -- I just noted after I submit. hehe

About "new Generator($arg)" I mean a method to flag the first argument on
function, that should identify that it should work differently or default
method (without allocate memory).
I guess that it is not implemented on PHP core, because until now have no
sense, but imagine something like that (I will write in PHP, but read it
like a C++):

PHP: new Generator(range(1, 1000))

C++ (range function):

if (getParentConstructor() === Generator::class) {
// Yield each one.
} else {
// Prepare on memory and return like an array.
}

In this case, when you call range() inside a Generator() constructor, then
the range() (in C++) will acts differently, like a xrange().




2017-03-17 22:57 GMT-03:00 Sara Golemon <pollita@php.net>:

> On Fri, Mar 17, 2017 at 8:40 PM, David Rodrigues <david.proweb@gmail.com>
> wrote:
> > There are some way to PHP be flagged before run some function, and
> > understand that you wants to return a Generator instead of array?
> > For instance: new Generator(range(1, 1000)) makes range() work like a
> > generator instead of return an array - it's an alternative to avoid new
> > keywords.
> > Or, maybe, some side implementation like Generator::range(1, 1000),
> > Generator::array_values($array), etc. (Currently, for instance, we can
> > simulate the range() Generator, but not array_values())
> >
> Why would array_values() as a generator be difficult?
>
> function generate_values(Traversable $in) {
> foreach ($in as $k => $v) {
> yield $k => $v;
> }
> }
>
> In general, your `new Generator($arr)` concept misses most of the
> usefulness of using a generator since arrays are already traversable,
> and you've already allocated all the space of a full container.
> Where's the benefit from making it a generator?
>
> -Sara
>



--
David Rodrigues
Sara Golemon
Re: [PHP-DEV] Let range() return a generator?
March 18, 2017 03:40AM
On Fri, Mar 17, 2017 at 9:10 PM, David Rodrigues <david.proweb@gmail.com> wrote:
> In this case, when you call range() inside a Generator() constructor, then
> the range() (in C++) will acts differently, like a xrange().
>
Doable: Yes.
Fundamentally broken within PHP's engine design: Definitely.

Calling scope should absolutely not have that kind of effect on what's
being called.

-Sara

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Johannes Schl├╝ter
Re: [PHP-DEV] Let range() return a generator?
March 20, 2017 02:30AM
On Fr, 2017-03-17 at 04:02 -0300, David Rodrigues wrote:
> I guess that a lot of PHP functions that could be replaced by a
> Generator (basically all array functions like array_values(),
> array_keys(), etc).
> But there are a big question: could it be applied to any case? It will
> be faster than just an array? Certainly it will be more memory
> optimized.

It's quite complicated - these new functions would have to keep a
copy/reference of the original array. Also we'd have to allow iterators
as parameter for array functions and we couldn't do everything, as
result of some of these array functions are stuck into other array
routines etc.

johannes


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Sorry, only registered users may post in this forum.

Click here to login