Greetings,
As suggested by several reviewers of a PR[1] I recently submitted, I'd
like to get feedback on letting custom Iterators be used in the current,
next, reset, and key functions. If this is something to move forward
with, I'll need some help with the RFC process.
Recent experiences trying to use these functions with a custom Iterator,
and a bug[2], led me to try and fix this. BC will occur when an object
implementing Iterator is passed to one of the functions, as the
interface methods will be called, instead of returning the objects
properties. The old behavior should be maintained for classes that do
not implement Iterator.
[1] https://github.com/php/php-src/pull/2176
[2] https://bugs.php.net/bug.php?id=49369
Thanks,
Dave
David Lundgren
dlundgren@syberisle.net
808.639.0365
GPG: 0x26F54D7F
Greetings,
As suggested by several reviewers of a PR[1] I recently submitted, I'd
like to get feedback on letting custom Iterators be used in the current,
next, reset, and key functions. If this is something to move forward
with, I'll need some help with the RFC process.Recent experiences trying to use these functions with a custom Iterator,
and a bug[2], led me to try and fix this. BC will occur when an object
implementing Iterator is passed to one of the functions, as the
interface methods will be called, instead of returning the objects
properties. The old behavior should be maintained for classes that do
not implement Iterator.[1] https://github.com/php/php-src/pull/2176
[2] https://bugs.php.net/bug.php?id=49369Thanks,
DaveDavid Lundgren
dlundgren@syberisle.net
808.639.0365
GPG: 0x26F54D7F--
I can't seem to recall specifics anymore but I do believe some people
would greatly prefer to remove the internal array pointer for
iteration and deprecate these functions. Maybe someone else can
remember more? Nikita and Bob, maybe?
On Wed, Oct 26, 2016 at 7:42 AM, David Lundgren dlundgren@syberisle.net
wrote:Greetings,
As suggested by several reviewers of a PR[1] I recently submitted, I'd
like to get feedback on letting custom Iterators be used in the current,
next, reset, and key functions. If this is something to move forward
with, I'll need some help with the RFC process.Recent experiences trying to use these functions with a custom Iterator,
and a bug[2], led me to try and fix this. BC will occur when an object
implementing Iterator is passed to one of the functions, as the
interface methods will be called, instead of returning the objects
properties. The old behavior should be maintained for classes that do
not implement Iterator.[1] https://github.com/php/php-src/pull/2176
[2] https://bugs.php.net/bug.php?id=49369Thanks,
DaveDavid Lundgren
dlundgren@syberisle.net
808.639.0365
GPG: 0x26F54D7F--
I can't seem to recall specifics anymore but I do believe some people
would greatly prefer to remove the internal array pointer for
iteration and deprecate these functions. Maybe someone else can
remember more? Nikita and Bob, maybe?
Yeah, I'm one of those people. In PHP 7 the most important user of the IAP,
foreach, was switched to use a more robust mechanism. I believe that at
this point, the concept of an internal array pointer has outlived its
usefulness and we should be working toward removing any APIs that publicly
expose it, including each and the next/current/key family of functions. I
will propose to deprecate each()
in particular for PHP 7.2, because it is
both more problematic and more useless than the others, but I'd like to see
the others go away in the long term as well. If people want fine-grained
control over array iteration, they should use an external iterator (aka
ArrayIterator), not an internal one.
Nikita
hi Nikita,
On Wed, Oct 26, 2016 at 7:42 AM, David Lundgren dlundgren@syberisle.net
wrote:Greetings,
As suggested by several reviewers of a PR[1] I recently submitted, I'd
like to get feedback on letting custom Iterators be used in the current,
next, reset, and key functions. If this is something to move forward
with, I'll need some help with the RFC process.Recent experiences trying to use these functions with a custom Iterator,
and a bug[2], led me to try and fix this. BC will occur when an object
implementing Iterator is passed to one of the functions, as the
interface methods will be called, instead of returning the objects
properties. The old behavior should be maintained for classes that do
not implement Iterator.[1] https://github.com/php/php-src/pull/2176
[2] https://bugs.php.net/bug.php?id=49369Thanks,
DaveDavid Lundgren
dlundgren@syberisle.net
808.639.0365
GPG: 0x26F54D7F--
I can't seem to recall specifics anymore but I do believe some people
would greatly prefer to remove the internal array pointer for
iteration and deprecate these functions. Maybe someone else can
remember more? Nikita and Bob, maybe?Yeah, I'm one of those people. In PHP 7 the most important user of the IAP,
foreach, was switched to use a more robust mechanism. I believe that at
this point, the concept of an internal array pointer has outlived its
usefulness and we should be working toward removing any APIs that publicly
expose it, including each and the next/current/key family of functions. I
will propose to deprecateeach()
in particular for PHP 7.2, because it is
both more problematic and more useless than the others, but I'd like to see
the others go away in the long term as well. If people want fine-grained
control over array iteration, they should use an external iterator (aka
ArrayIterator), not an internal one.
How do iterators compare to a for/while/custom loops using
next/current/etc? I did not bench it lately but last time there was a
significant impact when using Iterators.
I also think it is a good thing to clean up the ways to work with
arrays or iterable but we have to be very careful how we do it. I am
not sure an actual deprecation is a good thing in 7.x without breaking
any kind of tests out there. Indeed it will not break code but it is
rather bad to break tests and it is a very annoying thing to do while
trying to be good at using the latest PHP version.
I am not sure if a documentation+UPGRADE guide and all possible
communications about such deprecations would be enough. Maybe only
until we reach the last version before 8.0 (which can use actual
deprecations warnings, given we have more than 7.2 before 8.0).
Cheers,
Pierre
@pierrejoye | http://www.libgd.org
I also think it is a good thing to clean up the ways to work with
arrays or iterable but we have to be very careful how we do it. I am
not sure an actual deprecation is a good thing in 7.x without breaking
any kind of tests out there. Indeed it will not break code but it is
rather bad to break tests and it is a very annoying thing to do while
trying to be good at using the latest PHP version.
I understand the concern here but getting out deprecation notices out
early would be more important in my opinion. Additionally when we
decided to make PHP 7 our next release we had already released 5.6. I
pushed for a 5.7 to allow for deprecation notices as well as more time
to develop features for 7.0 but that's not the route we took. I point
this out to show that waiting for the last 7.x release is not prudent.
I also think it is a good thing to clean up the ways to work with
arrays or iterable but we have to be very careful how we do it. I am
not sure an actual deprecation is a good thing in 7.x without breaking
any kind of tests out there. Indeed it will not break code but it is
rather bad to break tests and it is a very annoying thing to do while
trying to be good at using the latest PHP version.
I don't follow this logic at all: isn't the whole point of deprecation
notices to make people notice them? If people run tests with
E_DEPRECATED
active, it's presumably because they want those tests to
tell them if they're using something deprecated; if people don't want
the deprecation notices to break their tests, they can configure their
test runner to ignore them. So who exactly is helped by not including
those notices?
Regards,
--
Rowan Collins
[IMSoP]
With regards to deprecating array-functions that operate on the
internal pointer - I'd like to just remind you of the fact that some
of these functions, reset()
and end()
in particular, are often used
not because someone cares about moving the internal pointer, but as a
means of getting the first/last items of an array.
If the internal pointers are removed, I'd like to suggest we improve
the reset()
and end()
functions rather than removing them - there is
an annoyance with these two functions presently: because they operate
on the internal pointer, the force you to introduce often meaningless
intermediary variables.
That is, for example:
$last = end(explode(",", $comma_separated_values));
Doesn't work. One is forced to introduce a variable:
$parts = explode(",", $comma_separated_values);
$last = end($parts);
If internal pointers are removed, maybe the reset()
and end()
functions could be made to actually work consistently? Whether applied
to an expression or variable.
On Wed, Oct 26, 2016 at 7:42 AM, David Lundgren dlundgren@syberisle.net
wrote:Greetings,
As suggested by several reviewers of a PR[1] I recently submitted, I'd
like to get feedback on letting custom Iterators be used in the current,
next, reset, and key functions. If this is something to move forward
with, I'll need some help with the RFC process.Recent experiences trying to use these functions with a custom Iterator,
and a bug[2], led me to try and fix this. BC will occur when an object
implementing Iterator is passed to one of the functions, as the
interface methods will be called, instead of returning the objects
properties. The old behavior should be maintained for classes that do
not implement Iterator.[1] https://github.com/php/php-src/pull/2176
[2] https://bugs.php.net/bug.php?id=49369Thanks,
DaveDavid Lundgren
dlundgren@syberisle.net
808.639.0365
GPG: 0x26F54D7F--
I can't seem to recall specifics anymore but I do believe some people
would greatly prefer to remove the internal array pointer for
iteration and deprecate these functions. Maybe someone else can
remember more? Nikita and Bob, maybe?Yeah, I'm one of those people. In PHP 7 the most important user of the IAP,
foreach, was switched to use a more robust mechanism. I believe that at
this point, the concept of an internal array pointer has outlived its
usefulness and we should be working toward removing any APIs that publicly
expose it, including each and the next/current/key family of functions. I
will propose to deprecateeach()
in particular for PHP 7.2, because it is
both more problematic and more useless than the others, but I'd like to see
the others go away in the long term as well. If people want fine-grained
control over array iteration, they should use an external iterator (aka
ArrayIterator), not an internal one.Nikita
With regards to deprecating array-functions that operate on the
internal pointer - I'd like to just remind you of the fact that some
of these functions,reset()
andend()
in particular, are often used
not because someone cares about moving the internal pointer, but as a
means of getting the first/last items of an array.If the internal pointers are removed, I'd like to suggest we improve
thereset()
andend()
functions rather than removing them - there is
an annoyance with these two functions presently: because they operate
on the internal pointer, the force you to introduce often meaningless
intermediary variables.That is, for example:
$last = end(explode(",", $comma_separated_values));
Doesn't work. One is forced to introduce a variable:
$parts = explode(",", $comma_separated_values); $last = end($parts);
If internal pointers are removed, maybe the
reset()
andend()
functions could be made to actually work consistently? Whether applied
to an expression or variable.
Yeah, I've been thinking about this as well. reset()
and end()
do seem to
be the most commonly used IAP functions -- while nobody actually cares
about their effect on the IAP. The thing is, if we remove all other
functions that allow users to inspect the IAP, then we can simply change
reset()
and end()
to return the first/last element. As they would no longer
actually modify the array, they would no longer accept their argument by
reference, so end(explode(...)) would also become legal (and additionally,
they would no longer have to do a full copy of their argument, like they
currently sometimes need to do).
Nikita
With regards to deprecating array-functions that operate on the
internal pointer - I'd like to just remind you of the fact that some
of these functions,reset()
andend()
in particular, are often used
not because someone cares about moving the internal pointer, but as a
means of getting the first/last items of an array.If the internal pointers are removed, I'd like to suggest we improve
thereset()
andend()
functions rather than removing them - there is
an annoyance with these two functions presently: because they operate
on the internal pointer, the force you to introduce often meaningless
intermediary variables.That is, for example:
$last = end(explode(",", $comma_separated_values));
Doesn't work. One is forced to introduce a variable:
$parts = explode(",", $comma_separated_values); $last = end($parts);
If internal pointers are removed, maybe the
reset()
andend()
functions could be made to actually work consistently? Whether applied
to an expression or variable.Yeah, I've been thinking about this as well.
reset()
andend()
do seem to
be the most commonly used IAP functions -- while nobody actually cares
about their effect on the IAP. The thing is, if we remove all other
functions that allow users to inspect the IAP, then we can simply change
reset()
andend()
to return the first/last element. As they would no longer
actually modify the array, they would no longer accept their argument by
reference, so end(explode(...)) would also become legal (and additionally,
they would no longer have to do a full copy of their argument, like they
currently sometimes need to do).Nikita
I think it makes much more sense to deprecate all of them and introduce
new ones that work in the way we want them to for several reasons.
end()
and reset()
would have to continue working as they do until
the next major release since people who use them might rely on the way
they work. This means in effect that nobody can make her PHP 7 code PHP
8 ready up front.
Instead we could directly introduce array_first()
and array_last()
with the next feature release -- even if the others are not deprecated
-- and everyone can update their code or at least use it in new code.
Changing end()
and reset()
in PHP 7 is imho way to dangerous!
Another often asked/proposed question is whether they should accept
traversables. I think especially for these two functions it's not easy
to simply accept any kind of traversable. Think of an unbuffered
database result which is effectively a remote pointer. Retrieving the
first and last would mean to iterate all the results.
An additional interface should be required for traversables in order to
work with first and last.
--
Richard "Fleshgrinder" Fussenegger
On second thought, I agree with that - changing reset()
and end()
doesn't make sense, because people know them and expect them to work
in a certain way. Likely a lot of people would actually continue to
use them with intermediary variables the way they do today. Better to
introduce a new pair of functions, since this will make it clear when
consumer code depends on the new behavior - if we update the existing
functions, that means you have to read code knowing which version of
these very common (and very old) functions you were expecting to call.
One thing though, since we have to introduce new functions, I would
not suggest these be array_first() and array_last(), but rather simply
first() and last(), and make then work with anything iterable, not
just arrays.
Retrieving the first and last would mean to iterate all the results.
Well, retrieving the last would - retrieving the first would mean
iterating only over the first result. For a lot of use-cases, and
unbuffered database results in particular, this is precisely what
you'd want.
An additional interface should be required for traversables in order to work with first and last.
I think it would be great to have that as an option - for cases where
you can and want to optimize retrieval of the last item, but I don't
think it should be required? For example, in the case of an unbuffered
database query, there is likely no optimization that can be made for
last() in the first place, since the database client/server are likely
using a protocol that doesn't even allow you to skip to the last
result; in that case, requiring everyone to implement a new interface,
which does nothing, isn't meaningful.
With regards to deprecating array-functions that operate on the
internal pointer - I'd like to just remind you of the fact that some
of these functions,reset()
andend()
in particular, are often used
not because someone cares about moving the internal pointer, but as a
means of getting the first/last items of an array.If the internal pointers are removed, I'd like to suggest we improve
thereset()
andend()
functions rather than removing them - there is
an annoyance with these two functions presently: because they operate
on the internal pointer, the force you to introduce often meaningless
intermediary variables.That is, for example:
$last = end(explode(",", $comma_separated_values));
Doesn't work. One is forced to introduce a variable:
$parts = explode(",", $comma_separated_values); $last = end($parts);
If internal pointers are removed, maybe the
reset()
andend()
functions could be made to actually work consistently? Whether applied
to an expression or variable.Yeah, I've been thinking about this as well.
reset()
andend()
do seem to
be the most commonly used IAP functions -- while nobody actually cares
about their effect on the IAP. The thing is, if we remove all other
functions that allow users to inspect the IAP, then we can simply change
reset()
andend()
to return the first/last element. As they would no longer
actually modify the array, they would no longer accept their argument by
reference, so end(explode(...)) would also become legal (and additionally,
they would no longer have to do a full copy of their argument, like they
currently sometimes need to do).Nikita
I think it makes much more sense to deprecate all of them and introduce
new ones that work in the way we want them to for several reasons.
end()
andreset()
would have to continue working as they do until
the next major release since people who use them might rely on the way
they work. This means in effect that nobody can make her PHP 7 code PHP
8 ready up front.Instead we could directly introduce
array_first()
andarray_last()
with the next feature release -- even if the others are not deprecated
-- and everyone can update their code or at least use it in new code.Changing
end()
andreset()
in PHP 7 is imho way to dangerous!Another often asked/proposed question is whether they should accept
traversables. I think especially for these two functions it's not easy
to simply accept any kind of traversable. Think of an unbuffered
database result which is effectively a remote pointer. Retrieving the
first and last would mean to iterate all the results.An additional interface should be required for traversables in order to
work with first and last.--
Richard "Fleshgrinder" Fussenegger
On second thought, I agree with that - changing
reset()
andend()
doesn't make sense, because people know them and expect them to work
in a certain way. Likely a lot of people would actually continue to
use them with intermediary variables the way they do today. Better
to introduce a new pair of functions, since this will make it clear
when consumer code depends on the new behavior - if we update the
existing functions, that means you have to read code knowing which
version of these very common (and very old) functions you were
expecting to call.One thing though, since we have to introduce new functions, I would
not suggest these be array_first() and array_last(), but rather
simply first() and last(), and make then work with anything iterable,
not just arrays.
first()
and last()
are extremely generic names and I am still hoping
to see nikic's scalar objects extension to land in core before 8. In
this case one would always call $x->first()
and $x->last()
.
Continuing with the array_
prefix makes perfect sense to me, even if
they accept \Traversable
instances as well. We also expect str_
prefixed functions to accept stringable objects, dont' we. It's just a
prefix for grouping and not necessarily a restrictions regarding the
types the function accepts.
Retrieving the first and last would mean to iterate all the
results.Well, retrieving the last would - retrieving the first would mean
iterating only over the first result. For a lot of use-cases, and
unbuffered database results in particular, this is precisely what
you'd want.An additional interface should be required for traversables in
order to work with first and last.I think it would be great to have that as an option - for cases
where you can and want to optimize retrieval of the last item, but I
don't think it should be required? For example, in the case of an
unbuffered database query, there is likely no optimization that can
be made for last() in the first place, since the database
client/server are likely using a protocol that doesn't even allow you
to skip to the last result; in that case, requiring everyone to
implement a new interface, which does nothing, isn't meaningful.
Not requiring the interface means that we violate the Liskow's
substitution principle, something I see too often in core and successful
PHP software out there. What if a traversable does not want the first
and last to be retrieved in this manner? Throw an exception? This
violates the principle since it is not expected to behave in this way.
Another possibility would it be to return null but then the question is,
was null returned because the first or last element is null or because I
cannot retrieve the first and last.
Making it explicit is much better.
--
Richard "Fleshgrinder" Fussenegger
I think you misunderstand.
I'm only suggesting that implementing first/last explicitly as an
optimization be optional.
If you call first() or last() on a traversable that doesn't implement
this interface, it will simply traverse the first item or traverse to
the end.
In other words, it'll always work, so it doesn't violate anything.
As said, in a lot of cases, such as traversing a stream of database
records, there is no optimization you can make for last() because
that's not possible with the driver.
So in that case, what you're proposing, is that all existing
traversables, such as DB adapters, shouldn't work with these functions
at all - everyone should have to go and implement this interface
first, even for traversable record sets where no optimization can be
made anyway and all you can do is actually fast-forward to the last
record by traversing the whole result set anyhow.
The only thing you'll get by forcing implementation of this interface,
is no existing traversable will work with these functions.
In addition, when everyone starts implementing this interface, those
libraries will lose backwards compatibility, since that interface will
not be available on older versions.
All so you can force people to implement an interface that, in many
cases, contains redundant code that simply traverses the entire result
set to the last item and returns it, for no meaningful reason.
On second thought, I agree with that - changing
reset()
andend()
doesn't make sense, because people know them and expect them to work
in a certain way. Likely a lot of people would actually continue to
use them with intermediary variables the way they do today. Better
to introduce a new pair of functions, since this will make it clear
when consumer code depends on the new behavior - if we update the
existing functions, that means you have to read code knowing which
version of these very common (and very old) functions you were
expecting to call.One thing though, since we have to introduce new functions, I would
not suggest these be array_first() and array_last(), but rather
simply first() and last(), and make then work with anything iterable,
not just arrays.
first()
andlast()
are extremely generic names and I am still hoping
to see nikic's scalar objects extension to land in core before 8. In
this case one would always call$x->first()
and$x->last()
.
Continuing with thearray_
prefix makes perfect sense to me, even if
they accept\Traversable
instances as well. We also expectstr_
prefixed functions to accept stringable objects, dont' we. It's just a
prefix for grouping and not necessarily a restrictions regarding the
types the function accepts.Retrieving the first and last would mean to iterate all the
results.Well, retrieving the last would - retrieving the first would mean
iterating only over the first result. For a lot of use-cases, and
unbuffered database results in particular, this is precisely what
you'd want.An additional interface should be required for traversables in
order to work with first and last.I think it would be great to have that as an option - for cases
where you can and want to optimize retrieval of the last item, but I
don't think it should be required? For example, in the case of an
unbuffered database query, there is likely no optimization that can
be made for last() in the first place, since the database
client/server are likely using a protocol that doesn't even allow you
to skip to the last result; in that case, requiring everyone to
implement a new interface, which does nothing, isn't meaningful.Not requiring the interface means that we violate the Liskow's
substitution principle, something I see too often in core and successful
PHP software out there. What if a traversable does not want the first
and last to be retrieved in this manner? Throw an exception? This
violates the principle since it is not expected to behave in this way.
Another possibility would it be to return null but then the question is,
was null returned because the first or last element is null or because I
cannot retrieve the first and last.Making it explicit is much better.
--
Richard "Fleshgrinder" Fussenegger
I think you misunderstand.
I'm only suggesting that implementing first/last explicitly as an
optimization be optional.If you call first() or last() on a traversable that doesn't implement
this interface, it will simply traverse the first item or traverse to
the end.In other words, it'll always work, so it doesn't violate anything.
As said, in a lot of cases, such as traversing a stream of database
records, there is no optimization you can make for last() because
that's not possible with the driver.So in that case, what you're proposing, is that all existing
traversables, such as DB adapters, shouldn't work with these functions
at all - everyone should have to go and implement this interface
first, even for traversable record sets where no optimization can be
made anyway and all you can do is actually fast-forward to the last
record by traversing the whole result set anyhow.The only thing you'll get by forcing implementation of this interface,
is no existing traversable will work with these functions.In addition, when everyone starts implementing this interface, those
libraries will lose backwards compatibility, since that interface will
not be available on older versions.All so you can force people to implement an interface that, in many
cases, contains redundant code that simply traverses the entire result
set to the last item and returns it, for no meaningful reason.
What I am concerned with is the opt-out case of this functionality. What
if I do not want that somebody misuses an unbuffered result set in such
a way: selecting 1,000 records just to throw 998 away. Your proposal is
very appealing in many ways but the opt-out means that I now need to
trigger a notice or throw an exception because there is no other way to
disallow this functionality.
Especially in the light of unbuffered result sets and generators which
can be traversed only once.
Another case is every unsorted form of collection, what is first, what
is last? How to you determine first and last if the keys of a
traversable are objects? Fail?
There are too many open questions in this regard. It's easier with the
primitive arrays because they have their limitations clearly defined
(maps keep insert order).
First and last only make sense for certain data structures but not for
all. Implementing something that just works might work for 80 % but not
for the rest and they have the problem now. I know that we have no means
to express proper data structures but this will not make it better.
Whether it makes it worse is another question that might help to decide.
--
Richard "Fleshgrinder" Fussenegger
What I am concerned with is the opt-out case of this functionality. What
if I do not want that somebody misuses an unbuffered result set in such
a way: selecting 1,000 records just to throw 998 away
In my opinion, that's a completely hypothetical use-case.
If I fetched 1000 records, most likely I'm doing something with those
1000 records.
If I happen to also be doing something special with the first or last
record, why should that require anything special from the collection
object itself?
If we're really this concerned about someone misunderstanding these
functions, I think honestly it would be better to not support
traversables at all - e.g. force them to use iterator_to_array()
instead, which makes it very obvious what's happening.
Perhaps that's a better solution altogether. It also fixes the case
where you accidentally traverse an open record-set twice, e.g. calling
first() and last() on the same iterable - that's not a problem case
you can fix, not even with an interface. In that case, the correct
thing is to fetch the records first, and/or adjust your query, depends
on the use-case, but accidentally iterating twice is likely never the
desired side-effect.
Another case is every unsorted form of collection, what is first, what is last?
Hypothetical. If it doesn't matter what's first or last, such as in an
unsorted form collection, why would you be calling the first or last
functions?
How to you determine first and last if the keys of a traversable are objects?
They're the first and last items to come out of the traversable. Seems
pretty straight forward to me.
But either way, I think I'm changing my mind about this one.
And if the these functions support only arrays, then also the names
should probably be array_first() and array_last() for consistency with
other array-only functions.
Perhaps better to make people be explicit, rather than trying to hide
side-effects to achieve shorter syntax...
I think you misunderstand.
I'm only suggesting that implementing first/last explicitly as an
optimization be optional.If you call first() or last() on a traversable that doesn't implement
this interface, it will simply traverse the first item or traverse to
the end.In other words, it'll always work, so it doesn't violate anything.
As said, in a lot of cases, such as traversing a stream of database
records, there is no optimization you can make for last() because
that's not possible with the driver.So in that case, what you're proposing, is that all existing
traversables, such as DB adapters, shouldn't work with these functions
at all - everyone should have to go and implement this interface
first, even for traversable record sets where no optimization can be
made anyway and all you can do is actually fast-forward to the last
record by traversing the whole result set anyhow.The only thing you'll get by forcing implementation of this interface,
is no existing traversable will work with these functions.In addition, when everyone starts implementing this interface, those
libraries will lose backwards compatibility, since that interface will
not be available on older versions.All so you can force people to implement an interface that, in many
cases, contains redundant code that simply traverses the entire result
set to the last item and returns it, for no meaningful reason.What I am concerned with is the opt-out case of this functionality. What
if I do not want that somebody misuses an unbuffered result set in such
a way: selecting 1,000 records just to throw 998 away. Your proposal is
very appealing in many ways but the opt-out means that I now need to
trigger a notice or throw an exception because there is no other way to
disallow this functionality.Especially in the light of unbuffered result sets and generators which
can be traversed only once.Another case is every unsorted form of collection, what is first, what
is last? How to you determine first and last if the keys of a
traversable are objects? Fail?There are too many open questions in this regard. It's easier with the
primitive arrays because they have their limitations clearly defined
(maps keep insert order).First and last only make sense for certain data structures but not for
all. Implementing something that just works might work for 80 % but not
for the rest and they have the problem now. I know that we have no means
to express proper data structures but this will not make it better.
Whether it makes it worse is another question that might help to decide.--
Richard "Fleshgrinder" Fussenegger
But either way, I think I'm changing my mind about this one.
And if the these functions support only arrays, then also the names
should probably be array_first() and array_last() for consistency with
other array-only functions.Perhaps better to make people be explicit, rather than trying to hide
side-effects to achieve shorter syntax...
+1
All of these concerns might be hypothetical but I see so much abuse
every day that I prefer to be super conservative rather than trusting
people to do the right thing.
--
Richard "Fleshgrinder" Fussenegger
Hi all,
But either way, I think I'm changing my mind about this one.
And if the these functions support only arrays, then also the names
should probably be array_first() and array_last() for consistency with
other array-only functions.Perhaps better to make people be explicit, rather than trying to hide
side-effects to achieve shorter syntax...+1
+1
There should be delete option. It's more useful if there is this option.
mixed array_first(array $arr [,bool $get_key = FALSE
[, bool
$remove_entry=FALSE]]);
mixed array_last(array $arr [,bool $get_key = FALSE
[, bool
$remove_entry=FALSE]]);
Problem with this is error condition. When array is empty, what should
be returned from these with default option? Returning NULL
for empty
array would be enough. IMO.
To clarify, do you use the return value of these functions or rely on
the IAP moving to also get the key?
Depends on code, but I usually use them just to get value of head/tail
element. It could be array_slice/splice, so I don't have much problem
with removing internal array position pointer. However, I still need
current()
or each()
to get value from returned array. This applies to
array_first/last($arr, TRUE);
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
There should be delete option. It's more useful if there is this option.
mixed array_first(array $arr [,bool $get_key =
FALSE
[, bool
$remove_entry=FALSE]]);
mixed array_last(array $arr [,bool $get_key =FALSE
[, bool
$remove_entry=FALSE]]);Problem with this is error condition. When array is empty, what should
be returned from these with default option? ReturningNULL
for empty
array would be enough. IMO.To clarify, do you use the return value of these functions or rely on
the IAP moving to also get the key?Depends on code, but I usually use them just to get value of head/tail
element. It could be array_slice/splice, so I don't have much problem
with removing internal array position pointer. However, I still need
current()
oreach()
to get value from returned array. This applies to
array_first/last($arr, TRUE);Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Flags are usually a bad design decision, it's better to make it fully
explicit and provide dedicated APIs for everything. This is much easier
for the reader and reading is more important than anything else.
/** Get the first element in the array. */
function array_first(array $array);
/** Get the key of the first element in the array. */
function array_first_key(array $array);
/** Get the last element in the array. */
function array_last(array $array);
/** Get the key of the last element in the array. */
function array_last_key(array $array);
/** Get and remove the first element from the array. */
function array_take_first(array $array);
/** Get the key of the first element in the array and remove it. */
function array_take_first_key(array $array);
/** Get and remove the last element from the array. */
function array_take_last(array $array);
/** Get the key of the last element in the array and remove it. */
function array_take_last_key(array $array);
Returning null
is imho the most sensible thing we can do if the array
is empty.
--
Richard "Fleshgrinder" Fussenegger
/** Get and remove the first element from the array. */
function array_take_first(array $array);/** Get and remove the last element from the array. */
function array_take_last(array $array);
These two already exist; they're called array_shift()
and array_pop()
.
The need for new functions for array_first() and array_last() is
precisely for when you don't want to modify the array.
Regards,
--
Rowan Collins
[IMSoP]
Hi, Fleshgrinder
There should be delete option. It's more useful if there is this option.
mixed array_first(array $arr [,bool $get_key =
FALSE
[, bool
$remove_entry=FALSE]]);
mixed array_last(array $arr [,bool $get_key =FALSE
[, bool
$remove_entry=FALSE]]);Problem with this is error condition. When array is empty, what should
be returned from these with default option? ReturningNULL
for empty
array would be enough. IMO.Flags are usually a bad design decision, it's better to make it fully
explicit and provide dedicated APIs for everything. This is much easier
for the reader and reading is more important than anything else.
It depends. Defining specific functions for a task could be bad design
also. We do design basic functions with flags usually, too.
That said, dedicated functions for getting first/last key/value sounds
good to me.
/** Get the first element in the array. */ function array_first(array $array); /** Get the key of the first element in the array. */ function array_first_key(array $array); /** Get the last element in the array. */ function array_last(array $array); /** Get the key of the last element in the array. */ function array_last_key(array $array); /** Get and remove the first element from the array. */ function array_take_first(array $array); /** Get the key of the first element in the array and remove it. */ function array_take_first_key(array $array); /** Get and remove the last element from the array. */ function array_take_last(array $array); /** Get the key of the last element in the array and remove it. */ function array_take_last_key(array $array);
Returning
null
is imho the most sensible thing we can do if the array
is empty.
A agree. That's the reason why I state return value is problem. However,
if (empty($arr)) {
// Do something
} else {
$first = array_first($arr);
}
shouldn't be difficult.
We should raise error for nonsense usage. Programmers have to check
empty()/isset() all the time anyway.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
It depends. Defining specific functions for a task could be bad design
also. We do design basic functions with flags usually, too.
I know that we have lots of them but they almost always end up in hard
to read and understand I-can-do-everything functions and their
implementation is also cluttered with branching.
That said, dedicated functions for getting first/last key/value sounds
good to me.A agree. That's the reason why I state return value is problem. However,
if (empty($arr)) {
// Do something
} else {
$first = array_first($arr);
}shouldn't be difficult.
We should raise error for nonsense usage. Programmers have to check
empty()/isset() all the time anyway.
I am an assert programmer, hence, I have no problem with an error in
such a case if others are fine with it.
@Rowan absolutely right, hence, if really needed:
function array_shift_key(array $array);
function array_pop_key(array $array);
--
Richard "Fleshgrinder" Fussenegger
On second thought, I agree with that - changing
reset()
andend()
doesn't make sense, because people know them and expect them to work
in a certain way. Likely a lot of people would actually continue to
use them with intermediary variables the way they do today.
Today?
In PHP 5.6.x I didn't have to use intermediate variables.
Being required to use them was new with PHP 7 and I suspect you will
find a lot of sites still using pre 7 because they haven't taken the
time to make sure every app they run works in PHP 7.
All my production servers still run 5.6.x for that reason, I'm only now
starting to port the apps I can now that it appears the PECL modules I
need have finally all been updated.
The php apps I am fixing are currently littered with code like this:
$SEVENFIX = explode('.', $rs[0]->cover);
if(end($SEVENFIX) == "whatever") {
// do stuff
}
before trying the app in my 7.1.0RCx test servers they worked just fine as
if(end(explode('.', $rs[0]->cover)) == "whatever") {
// do stuff
}
So I suppose some people might "continue" to use them with intermediary
but a lot of code that hasn't been ported to 7 doesn't currently.
On second thought, I agree with that - changing
reset()
andend()
doesn't make sense, because people know them and expect them to work
in a certain way. Likely a lot of people would actually continue to
use them with intermediary variables the way they do today.Today?
In PHP 5.6.x I didn't have to use intermediate variables.
You did. You simply suppressed the error in PHP 5. In PHP 7 the error
classification changed, so you're no longer suppressing it. See:
https://3v4l.org/2R8Vp
Prior to the PHP 7 release I suggested marking a number of functions
(array_pop/shift, reset, end) as prefer-ref, so they could be used without
warning, see http://markmail.org/message/peefyi46iz2amdbq. Nothing really
came of it at the time. Just mentioning it here because we can already
avoid the warning right now -- we don't have to drop the IAP first. Both
issues are independent.
However, introducing array_first/last is still better than using reset/end
etc, because these functions can easily trigger an unnecessary array copy,
while array_first/last wouldn't have that problem.
Nikita
Being required to use them was new with PHP 7 and I suspect you will find
a lot of sites still using pre 7 because they haven't taken the time to
make sure every app they run works in PHP 7.All my production servers still run 5.6.x for that reason, I'm only now
starting to port the apps I can now that it appears the PECL modules I need
have finally all been updated.The php apps I am fixing are currently littered with code like this:
$SEVENFIX = explode('.', $rs[0]->cover);
if(end($SEVENFIX) == "whatever") {
// do stuff
}before trying the app in my 7.1.0RCx test servers they worked just fine as
if(end(explode('.', $rs[0]->cover)) == "whatever") {
// do stuff
}So I suppose some people might "continue" to use them with intermediary
but a lot of code that hasn't been ported to 7 doesn't currently.
I think it makes much more sense to deprecate all of them and introduce
new ones that work in the way we want them to for several reasons.
end()
andreset()
would have to continue working as they do until
the next major release since people who use them might rely on the way
they work. This means in effect that nobody can make her PHP 7 code PHP
8 ready up front.Instead we could directly introduce
array_first()
andarray_last()
with the next feature release -- even if the others are not deprecated
-- and everyone can update their code or at least use it in new code.
I've always felt like these functions were "missing" from the language -
there are a number of ways you can get the first or last item in an
array, but all have side effects, because they're not designed for this
purpose. It just so happens that - most of the time - reset()
and end()
have the smallest side effects.
I can't remember if it was an earlier discussion here, or somewhere
else, that pointed to getting the first and last key as an extra use
case worth considering. It's currently possible (if awkward) with key()
.
I think it would make sense to, in the same version:
- deprecate
reset()
,end()
,each()
, andkey()
- introduce array_first(), array_last(), array_first_key() and
array_last_key() - document replacements for whatever other use cases we can find examples of
Doing them all at once makes the messaging much clearer - this family of
functions is going to be removed; and here are the new functions you can
start using immediately instead.
Regards,
--
Rowan Collins
[IMSoP]
I think it makes much more sense to deprecate all of them and introduce
new ones that work in the way we want them to for several reasons.
end()
andreset()
would have to continue working as they do until
the next major release since people who use them might rely on the way
they work. This means in effect that nobody can make her PHP 7 code PHP
8 ready up front.Instead we could directly introduce
array_first()
andarray_last()
with the next feature release -- even if the others are not deprecated
-- and everyone can update their code or at least use it in new code.I've always felt like these functions were "missing" from the language -
there are a number of ways you can get the first or last item in an
array, but all have side effects, because they're not designed for this
purpose. It just so happens that - most of the time -reset()
andend()
have the smallest side effects.I can't remember if it was an earlier discussion here, or somewhere
else, that pointed to getting the first and last key as an extra use
case worth considering. It's currently possible (if awkward) withkey()
.I think it would make sense to, in the same version:
- deprecate
reset()
,end()
,each()
, andkey()
- introduce array_first(), array_last(), array_first_key() and
array_last_key()- document replacements for whatever other use cases we can find
examples ofDoing them all at once makes the messaging much clearer - this family of
functions is going to be removed; and here are the new functions you can
start using immediately instead.
I fully agree.
--
Christoph M. Becker
- deprecate
reset()
,end()
,each()
, andkey()
- introduce array_first(), array_last(), array_first_key() and
array_last_key()- document replacements for whatever other use cases we can find
examples of
As a user I certainly like those names better. Semantic function names
are a definite win in my view.
- deprecate
reset()
,end()
,each()
, andkey()
- introduce array_first(), array_last(), array_first_key() and
array_last_key()- document replacements for whatever other use cases we can find
examples ofAs a user I certainly like those names better. Semantic function names
are a definite win in my view.
Question: Now that we have "iterable" as a type, should we be adding
more array-specific functions or should such operations be designed, and
named, to operate on any iterable? (first(), first_key(), etc.)
--Larry Garfield
- deprecate
reset()
,end()
,each()
, andkey()
- introduce array_first(), array_last(), array_first_key() and
array_last_key()- document replacements for whatever other use cases we can find
examples ofAs a user I certainly like those names better. Semantic function names are
a definite win in my view.Question: Now that we have "iterable" as a type, should we be adding more
array-specific functions or should such operations be designed, and named,
to operate on any iterable? (first(), first_key(), etc.)
At least for last and last-key I do not think we should make them work
with any iterable. My reasoning is that we do not want to consume the
iterator for them because many iterators are not rewindable (such as
generators). The first and first-key routines should generally work
because rewind(); valid();
current();
rewind();
doesn't contain a
next()
call.
Rewinding without iterating works for generators: https://3v4l.org/O7ZKO
Rewinding after a next()
call: https://3v4l.org/QI434
- deprecate
reset()
,end()
,each()
, andkey()
- introduce array_first(), array_last(), array_first_key() and
array_last_key()- document replacements for whatever other use cases we can find
examples ofAs a user I certainly like those names better. Semantic function names are
a definite win in my view.Question: Now that we have "iterable" as a type, should we be adding more
array-specific functions or should such operations be designed, and named,
to operate on any iterable? (first(), first_key(), etc.)At least for last and last-key I do not think we should make them work
with any iterable. My reasoning is that we do not want to consume the
iterator for them because many iterators are not rewindable (such as
generators). The first and first-key routines should generally work
becauserewind(); valid();
current();
rewind();
doesn't contain a
next()
call.Rewinding without iterating works for generators: https://3v4l.org/O7ZKO
Rewinding after anext()
call: https://3v4l.org/QI434
Additionally consuming the iterator would be an algorithmic complexity
of O(n) whereas for an array would just be O(1). So not only is it
annoying that the iterator is consumed and can't be guaranteed to be
rewound it is also costly.
The first and first-key routines do not have these issues.
Question: Now that we have "iterable" as a type, should we be adding more
array-specific functions or should such operations be designed, and named,
to operate on any iterable? (first(), first_key(), etc.)
At least for last and last-key I do not think we should make them work
with any iterable. My reasoning is that we do not want to consume the
iterator for them because many iterators are not rewindable (such as
generators). The first and first-key routines should generally work
becauserewind(); valid();
current();
rewind();
doesn't contain a
next()
call.Rewinding without iterating works for generators: https://3v4l.org/O7ZKO
Rewinding after anext()
call: https://3v4l.org/QI434
Additionally consuming the iterator would be an algorithmic complexity
of O(n) whereas for an array would just be O(1). So not only is it
annoying that the iterator is consumed and can't be guaranteed to be
rewound it is also costly.The first and first-key routines do not have these issues.
Might it make sense then to have
first(iterable)
first_key(iterable)
array_last(array)
array_last_key(array)
It's not quite as parallel, but it does provide more broadly compatible
functionality.
If we're concerned about pw0ning the "first" function name, perhaps it's
time to start a new prefix:
iter_first(iterable)
iter_first_key(iterable)
array_last(array)
array_last_key(array)
Which gives a natural place to start putting iterable-friendly
alternates of the various array_* functions, for those that make sense.
(think iter_fold(), iter_map(), iter_filter(), etc.)
(Insert debate about parameter order and method-based alternatives here.)
--Larry Garfield
If we're concerned about pw0ning the "first" function name, perhaps it's
time to start a new prefix:iter_first(iterable)
iter_first_key(iterable)
array_last(array)
array_last_key(array)Which gives a natural place to start putting iterable-friendly
alternates of the various array_* functions, for those that make sense.
(think iter_fold(), iter_map(), iter_filter(), etc.)(Insert debate about parameter order and method-based alternatives here.)
A couple of things before my next idea:
- I don't know if this has been proposed before
- I do not understand the internals code well enough
- This is probably something for PHP 8, but it'd be great for PHP 7.2!
- ArrayIterator does what I am proposing, but adds overhead for users
What if we made ArrayIterator transparently wrap all array's?
Then we could go with iter_* functions, deprecate array_* functions, and
have syntax that flows like the following?
===
$ary = [1,2,3];
$ary->current(); // returns 1
$ary->reset(); // array is now at index:0
$ary->next(); // array is now at index:1 current => 2
$ary->key(); // 1
// I'll bikeshed the Array type now
$ary->search(2); // 1
$ary->in(2); // true
$ary->keys(); // [0,1,2]
// threw these in here for good measure, part of \Iterator interface?
$ary->first(); // 1
$ary->last(); // 3
Dave
David Lundgren
dlundgren@syberisle.net
GPG: 0x26F54D7F
Hi David and all,
What if we made ArrayIterator transparently wrap all array's?
If you take a look at SPL array object code, you'll see why there are
so many missing functions. It's just pain for me to write new method
even with simple one.
Can we get rid of some features from array objects? and make it
simpler? e.g. We don't need 2 ways to store array data, I suppose.
Why there are 2 ways?
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
What if we made ArrayIterator transparently wrap all array's?
If you take a look at SPL array object code, you'll see why there are
so many missing functions. It's just pain for me to write new method
even with simple one.
So why don't people use SPL array objects where they want this
repackaging of the procedural code? It has not gained traction as a full
time replacement, but why not?
Can we get rid of some features from array objects? and make it
simpler? e.g. We don't need 2 ways to store array data, I suppose.
Why there are 2 ways?
There are more ways to a lot of things than are actually needed, but
stripping out 'duplicates' needs agreement on which are the better way.
Personally I don't see the 'advantages' of completely remodelling the
way the procedural functions work. If you want yet another user
interface, build it as an object class.
The bulk of the duplication is down to people adding their own view on
how things should be done, and perhaps it is time to decide what is the
core set of functions needed to handle simple structures and move
everything else into optional extensions ... beginners don't need all
the heavy stuff and I include Reflections in that ... A starter manual
does not need the bulk of the code that is weighing down PHP today.
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
Hi Larry,
Might it make sense then to have
first(iterable)
first_key(iterable)
array_last(array)
array_last_key(array)
array_ prefix is required for all new array functions, IMHO.
I don't have strong opinion for iter_ prefix for now, but if iter_
prefix is used, it should be used consistently.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
On 31.10.2016 at 18:27m Larry Garfield wrote:
- deprecate
reset()
,end()
,each()
, andkey()
- introduce array_first(), array_last(), array_first_key() and
array_last_key()- document replacements for whatever other use cases we can find
examples ofAs a user I certainly like those names better. Semantic function names
are a definite win in my view.Question: Now that we have "iterable" as a type, should we be adding
more array-specific functions or should such operations be designed, and
named, to operate on any iterable? (first(), first_key(), etc.)
According to the earlier discussion it is not clear if we want these
functions to operate on Iterables (consider Generators). Anyhow, we
probably can't introduce a function named first() for BC reasons.
--
Christoph M. Becker
I'd like to just remind you of the fact that some
of these functions,reset()
andend()
in particular, are often used
not because someone cares about moving the internal pointer, but as a
means of getting the first/last items of an array.
I'm one of them.
--
Yasuo Ohgaki
yohgaki@ohgaki.net
I'd like to just remind you of the fact that some
of these functions,reset()
andend()
in particular, are often used
not because someone cares about moving the internal pointer, but as a
means of getting the first/last items of an array.I'm one of them.
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Are you after the last value, the last key, or both?
I'd like to just remind you of the fact that some
of these functions,reset()
andend()
in particular, are often used
not because someone cares about moving the internal pointer, but as a
means of getting the first/last items of an array.I'm one of them.
--
Yasuo Ohgaki
yohgaki@ohgaki.netAre you after the last value, the last key, or both?
To clarify, do you use the return value of these functions or rely on
the IAP moving to also get the key?
Hi Nikita,
Nikita Popov wrote:
I can't seem to recall specifics anymore but I do believe some people
would greatly prefer to remove the internal array pointer for
iteration and deprecate these functions. Maybe someone else can
remember more? Nikita and Bob, maybe?Yeah, I'm one of those people. In PHP 7 the most important user of the IAP,
foreach, was switched to use a more robust mechanism. I believe that at
this point, the concept of an internal array pointer has outlived its
usefulness and we should be working toward removing any APIs that publicly
expose it, including each and the next/current/key family of functions. I
will propose to deprecateeach()
in particular for PHP 7.2, because it is
both more problematic and more useless than the others, but I'd like to see
the others go away in the long term as well. If people want fine-grained
control over array iteration, they should use an external iterator (aka
ArrayIterator), not an internal one.
I'm sure I've suggested this before, but couldn't we drop the IAP
without getting rid of these functions? They could maintain their own
map of arrays to positions (effectively emulating the IAP), for example.
Thanks.
--
Andrea Faulds
https://ajf.me/
Hi David,
David Lundgren wrote:
As suggested by several reviewers of a PR[1] I recently submitted, I'd
like to get feedback on letting custom Iterators be used in the current,
next, reset, and key functions. If this is something to move forward
with, I'll need some help with the RFC process.Recent experiences trying to use these functions with a custom Iterator,
and a bug[2], led me to try and fix this. BC will occur when an object
implementing Iterator is passed to one of the functions, as the
interface methods will be called, instead of returning the objects
properties. The old behavior should be maintained for classes that do
not implement Iterator.
A concern that strikes me is that it's possible some existing code uses
these functions precisely because they don't support Iterators, because
the author wants to iterate over an object's properties.
What would be the proposed alternative in that case? Reflection?
I think it's unfortunate that PHP has two iteration behaviours for
objects, namely iterating over properties, and custom iterators. I think
those ought to be separate, rather than the latter overriding the former.
Thanks!
--
Andrea Faulds
https://ajf.me/
A concern that strikes me is that it's possible some existing code uses
these functions precisely because they don't support Iterators, because
the author wants to iterate over an object's properties.
I hadn't thought about that particular use case. I also hadn't ever
tried using these functions on non-arrays before I recently attempted
using them with an Iterator.
What would be the proposed alternative in that case? Reflection?
I would think that Reflection would be necessary to get the
private/protected properties, but these functions currently allow
iteration over private/protected properties of an object. This should be
limited to public properties similar to the way foreach is limited. But
that's another issue.
I think it's unfortunate that PHP has two iteration behaviours for
objects, namely iterating over properties, and custom iterators. I think
those ought to be separate, rather than the latter overriding the former.
As a user it came as a surprise that I couldn't use an Iterator where an
array was being used, as they are used interchangeable in some other
contexts.
I'll also admit that I don't normally read the docs until I have
problems. The behavior with passing objects to those functions is only
documented by a user comment.
Dave
David Lundgren
dlundgren@syberisle.net
GPG: 0x26F54D7F
Thank you everyone for your feedback.
Nikita's post about wrapping the array with an ArrayIterator provides
the best approach to allow an array or Traversable to be used. This will
also provide the greatest backwards compatible usage for those of us
writing user code that would need to be compatible with 5.6 and 7.x.
I think it would be bad to remove these functions and force users to
wrap arrays with ArrayIterator, just to manually iterate an array. After
spending a little time looking through how these functions are being
used in frameworks and libraries, removing them seems like it will cause
more harm than good, even in a future version of the language.
Toward Andrea's suggestion of replacing the IAP in these functions, I'll
take a look and see what I can come up with. Considering the current
usage of these functions, I don't think this will generate a lot of
overhead.
Again, thanks for the feedback!
Dave
Greetings,
As suggested by several reviewers of a PR[1] I recently submitted, I'd
like to get feedback on letting custom Iterators be used in the current,
next, reset, and key functions. If this is something to move forward
with, I'll need some help with the RFC process.Recent experiences trying to use these functions with a custom Iterator,
and a bug[2], led me to try and fix this. BC will occur when an object
implementing Iterator is passed to one of the functions, as the
interface methods will be called, instead of returning the objects
properties. The old behavior should be maintained for classes that do
not implement Iterator.[1] https://github.com/php/php-src/pull/2176
[2] https://bugs.php.net/bug.php?id=49369Thanks,
Dave
--
David Lundgren
dlundgren@syberisle.net
GPG: 0x26F54D7F
I think it would be bad to remove these functions and force users to
wrap arrays with ArrayIterator, just to manually iterate an array. After
spending a little time looking through how these functions are being
used in frameworks and libraries, removing them seems like it will cause
more harm than good, even in a future version of the language.
Can you show some examples of frameworks and libraries you found where
it would cause more harm than good?
I think it would be bad to remove these functions and force users to
wrap arrays with ArrayIterator, just to manually iterate an array. After
spending a little time looking through how these functions are being
used in frameworks and libraries, removing them seems like it will cause
more harm than good, even in a future version of the language.Can you show some examples of frameworks and libraries you found where
it would cause more harm than good?
Apologies, that was a subjective statement. I also made it appear that
the usage of these functions was greater than it may really be, and
would cripple said projects, that was not my intention, and most
definitely not the case.
These are the ones I remember, and another way could be used if
current/next/key were not available for these contexts:
Yii CMarkdownParser: https://git.io/vXCiy
ZF2 stdlib FastPriorityQueue: https://git.io/vXCiH
Drupal DI Container: https://git.io/vXCPB
Symfony MO file loader: https://git.io/vXCPK
Symfony HttpFoundation Request: https://git.io/vXCXW
Dave
David Lundgren
dlundgren@syberisle.net
GPG: 0x26F54D7F
I think it would be bad to remove these functions and force users to
wrap arrays with ArrayIterator, just to manually iterate an array. After
spending a little time looking through how these functions are being
used in frameworks and libraries, removing them seems like it will cause
more harm than good, even in a future version of the language.Can you show some examples of frameworks and libraries you found where
it would cause more harm than good?Apologies, that was a subjective statement. I also made it appear that
the usage of these functions was greater than it may really be, and
would cripple said projects, that was not my intention, and most
definitely not the case.These are the ones I remember, and another way could be used if
current/next/key were not available for these contexts:Yii CMarkdownParser: https://git.io/vXCiy
ZF2 stdlib FastPriorityQueue: https://git.io/vXCiH
Drupal DI Container: https://git.io/vXCPB
Symfony MO file loader: https://git.io/vXCPK
Symfony HttpFoundation Request: https://git.io/vXCXWDave
David Lundgren
dlundgren@syberisle.net
GPG: 0x26F54D7F--
Many of these just seem to use current
to get the first item and
would easily migrate to a new API such as first()
.