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?
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 therange()
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 ofrange()
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
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 therange()
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 ofrange()
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
I guess that a lot of PHP functions that could be replaced by a
Generator (basically all array functions likearray_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
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
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
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.
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:
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
--
--
David Rodrigues
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)) makesrange()
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 therange()
Generator, but notarray_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
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)) makesrange()
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 therange()
Generator, but notarray_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
In this case, when you call
range()
inside a Generator() constructor, then
therange()
(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