array_reject() as counterpart of array_filter()

  111722
August 30, 2020 14:38 david.proweb@gmail.com (David Rodrigues)
Currently we have array_filter(), but sometimes we need an inverse function
like array_reject().

array_reject('is_null', [ 1, 2, null, 3 ]); // [ 1, 2, 3 ]

It could be easily implemented with:

function array_reverse($fn, $arr) { return array_filter(fn($item) =>
!$fn($item), $arr); }

Anyway, I think that It should be implemented by core, once that we have
array_filter().
  111733
August 30, 2020 23:54 larry@garfieldtech.com ("Larry Garfield")
On Sun, Aug 30, 2020, at 9:38 AM, David Rodrigues wrote:
> Currently we have array_filter(), but sometimes we need an inverse function > like array_reject(). > > array_reject('is_null', [ 1, 2, null, 3 ]); // [ 1, 2, 3 ] > > It could be easily implemented with: > > function array_reverse($fn, $arr) { return array_filter(fn($item) => > !$fn($item), $arr); } > > Anyway, I think that It should be implemented by core, once that we have > array_filter().
Any boolean function can be inverted with a simple ! in a short closure. I don't really see a need to do that in C. --Larry Garfield
  111737
August 31, 2020 13:52 josh@joshbruce.dev (Josh Bruce)
Just to confirm

array_filter(“!is_int”, $collection)

Would result in a collection of only non-integers??

I do think there’s something to be said for the communication of intent without syntax.

array_without or array_reject reads easier to me than making sure to watch for the bang.

Cheers,
Josh

>> On Aug 30, 2020, at 6:55 PM, Larry Garfield <larry@garfieldtech.com> wrote: >> >> On Sun, Aug 30, 2020, at 9:38 AM, David Rodrigues wrote: >> Currently we have array_filter(), but sometimes we need an inverse function >> like array_reject(). >> array_reject('is_null', [ 1, 2, null, 3 ]); // [ 1, 2, 3 ] >> It could be easily implemented with: >> function array_reverse($fn, $arr) { return array_filter(fn($item) => >> !$fn($item), $arr); } >> Anyway, I think that It should be implemented by core, once that we have >> array_filter(). > > Any boolean function can be inverted with a simple ! in a short closure. I don't really see a need to do that in C. > > --Larry Garfield > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php
  111738
August 31, 2020 14:08 chasepeeler@gmail.com (Chase Peeler)
On Mon, Aug 31, 2020 at 9:52 AM Josh Bruce <josh@joshbruce.dev> wrote:

> Just to confirm > > array_filter(“!is_int”, $collection) > > Would result in a collection of only non-integers?? > > No, you'd have to put it in a closure
The original poster had a typo, I think, and meant array_reject not array_reverse. He basically implemented the solution that Larry was referring to, before Larry referred to it. function array_reject(Callable $c, Array $a){ return array_filter(fn($item) => !$c($i), $a); } $non_ints = array_reject('is_int',[1,2,'a',3.5]); If you don't want to write your own array_reject method, and just handle it case-by-case, then it's still trivial $non_ints = array_filter(fn($i) => !is_int($i), [1,2,'a',3.5]); I do think there’s something to be said for the communication of intent
> without syntax. > > array_without or array_reject reads easier to me than making sure to watch > for the bang. > > I agree with Larry that userland implementation is trivial enough that it
doesn't really need to be implemented in core. It's just syntactic sugar that's probably more trouble than it's worth. That being said, I'm by far an expert when it comes to core, so I can't really say 1.) what performance benefits it would provide or 2.) how hard (or easy) it would be to implement.
> Cheers, > Josh > > >> On Aug 30, 2020, at 6:55 PM, Larry Garfield <larry@garfieldtech.com> > wrote: > >> > >> On Sun, Aug 30, 2020, at 9:38 AM, David Rodrigues wrote: > >> Currently we have array_filter(), but sometimes we need an inverse > function > >> like array_reject(). > >> array_reject('is_null', [ 1, 2, null, 3 ]); // [ 1, 2, 3 ] > >> It could be easily implemented with: > >> function array_reverse($fn, $arr) { return array_filter(fn($item) => > >> !$fn($item), $arr); } > >> Anyway, I think that It should be implemented by core, once that we have > >> array_filter(). > > > > Any boolean function can be inverted with a simple ! in a short > closure. I don't really see a need to do that in C. > > > > --Larry Garfield > > > > -- > > PHP Internals - PHP Runtime Development Mailing List > > To unsubscribe, visit: https://www.php.net/unsub.php > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > >
-- Chase Peeler chasepeeler@gmail.com
  111739
August 31, 2020 14:41 david.proweb@gmail.com (David Rodrigues)
> The original poster had a typo, I think, and meant array_reject not > array_reverse. He basically implemented the solution that Larry was > referring to, before Larry referred to it.
Yes! It means to be "array_reject()" instead of "array_reverse()". And my syntax is wrong too, actually it should be array_reject(array, callback) like array_filter(array, callback).
> I agree with Larry that userland implementation is trivial enough that it > doesn't really need to be implemented in core. It's just syntactic sugar > that's probably more trouble than it's worth. That being said, I'm by far > an expert when it comes to core, so I can't really say 1.) what performance
> benefits it would provide or 2.) how hard (or easy) it would be to > implement.
1. array_reject() should be 70% faster than array_filter(arr, fn() ...) version; 2. basically is just replicate array_filter() code with a "not" operator at some point. But, analysing array_filter() now, I think that we can consider just a new flag, instead a new function: array_filter($array, $callback, ARRAY_FILTER_REJECT), so the implementation will be very simple and will not need to create a new function to userland. PS.: the array_reject() name suggestion is based on the lodash version ( https://lodash.com/docs/4.17.15#reject). Atenciosamente, David Rodrigues Em seg., 31 de ago. de 2020 às 11:08, Chase Peeler <chasepeeler@gmail.com> escreveu:
> On Mon, Aug 31, 2020 at 9:52 AM Josh Bruce <josh@joshbruce.dev> wrote: > > > Just to confirm > > > > array_filter(“!is_int”, $collection) > > > > Would result in a collection of only non-integers?? > > > > > No, you'd have to put it in a closure > > The original poster had a typo, I think, and meant array_reject not > array_reverse. He basically implemented the solution that Larry was > referring to, before Larry referred to it. > > function array_reject(Callable $c, Array $a){ > return array_filter(fn($item) => !$c($i), $a); > } > > $non_ints = array_reject('is_int',[1,2,'a',3.5]); > > If you don't want to write your own array_reject method, and just handle it > case-by-case, then it's still trivial > > $non_ints = array_filter(fn($i) => !is_int($i), [1,2,'a',3.5]); > > I do think there’s something to be said for the communication of intent > > without syntax. > > > > array_without or array_reject reads easier to me than making sure to > watch > > for the bang. > > > > > I agree with Larry that userland implementation is trivial enough that it > doesn't really need to be implemented in core. It's just syntactic sugar > that's probably more trouble than it's worth. That being said, I'm by far > an expert when it comes to core, so I can't really say 1.) what performance > benefits it would provide or 2.) how hard (or easy) it would be to > implement. > > > > > Cheers, > > Josh > > > > >> On Aug 30, 2020, at 6:55 PM, Larry Garfield <larry@garfieldtech.com> > > wrote: > > >> > > >> On Sun, Aug 30, 2020, at 9:38 AM, David Rodrigues wrote: > > >> Currently we have array_filter(), but sometimes we need an inverse > > function > > >> like array_reject(). > > >> array_reject('is_null', [ 1, 2, null, 3 ]); // [ 1, 2, 3 ] > > >> It could be easily implemented with: > > >> function array_reverse($fn, $arr) { return array_filter(fn($item) => > > >> !$fn($item), $arr); } > > >> Anyway, I think that It should be implemented by core, once that we > have > > >> array_filter(). > > > > > > Any boolean function can be inverted with a simple ! in a short > > closure. I don't really see a need to do that in C. > > > > > > --Larry Garfield > > > > > > -- > > > PHP Internals - PHP Runtime Development Mailing List > > > To unsubscribe, visit: https://www.php.net/unsub.php > > > > -- > > PHP Internals - PHP Runtime Development Mailing List > > To unsubscribe, visit: https://www.php.net/unsub.php > > > > > > -- > Chase Peeler > chasepeeler@gmail.com >
  111740
August 31, 2020 14:55 pollita@php.net (Sara Golemon)
On Mon, Aug 31, 2020 at 9:41 AM David Rodrigues proweb@gmail.com>
wrote:

> > I agree with Larry that userland implementation is trivial enough that it > > doesn't really need to be implemented in core. It's just syntactic sugar > > that's probably more trouble than it's worth. That being said, I'm by > far > > an expert when it comes to core, so I can't really say 1.) what > performance > > benefits it would provide or 2.) how hard (or easy) it would be to > > implement. > > 1. array_reject() should be 70% faster than array_filter(arr, fn() ...) > version; > > Citation Needed.
Just to be clear, I think you're referring to "compared to the case of a bare string callable", e.g.: array_filter($arr, 'is_numeric') vs. array_filter($arr, fn($x) => !is_numeric($x)); "Citation required" still stands in that case, but even if that function call overhead does amount to 70% (and for inlined functions like is_numeric it might), I would say that's not cause to add complexity to the filter function, but rather cause to look at ways to optimize the code that exists in the wild. It should be possible for the engine (at some layer) to look at that closure and see that it's just negating some proxied call and elide setting up the intermediate frame. Microoptimizations SHOULD be the engine's job, not userspace's. -Sara
  111741
August 31, 2020 15:35 david.proweb@gmail.com (David Rodrigues)
> Just to be clear, I think you're referring to "compared to the case of a bare string callable", e.g.: array_filter($arr, 'is_numeric') vs.
array_filter($arr, fn($x) => !is_numeric($x)); Yes, because I can optimize it when array_filter() is "positive-only", but I can't when I need to be "negative-only", so I depend on a fn($x) => !is_numeric($x). I not have a php-src enabled for now, but I pretends to have soon so I can try to apply it directly to C and compile it, so for now I am limited to what PHP could do.
> "Citation required" still stands in that case, but even if that function call overhead does amount to 70% (and for inlined functions like is_numeric
it might), I would say that's not cause to add complexity to the filter function, but rather cause to look at ways to optimize the code that exists in the wild. It should be possible for the engine (at some layer) to look at that closure and see that it's just negating some proxied call and elide setting up the intermediate frame. Microoptimizations SHOULD be the engine's job, not userspace's. I really think that it should be a good solution, but how hard should it be to create a proxy like that? Atenciosamente, David Rodrigues Em seg., 31 de ago. de 2020 às 11:55, Sara Golemon <pollita@php.net> escreveu:
> On Mon, Aug 31, 2020 at 9:41 AM David Rodrigues proweb@gmail.com> > wrote: > >> > I agree with Larry that userland implementation is trivial enough that >> it >> > doesn't really need to be implemented in core. It's just syntactic sugar >> > that's probably more trouble than it's worth. That being said, I'm by >> far >> > an expert when it comes to core, so I can't really say 1.) what >> performance >> > benefits it would provide or 2.) how hard (or easy) it would be to >> > implement. >> >> 1. array_reject() should be 70% faster than array_filter(arr, fn() ...) >> version; >> >> > Citation Needed. > > Just to be clear, I think you're referring to "compared to the case of a > bare string callable", e.g.: array_filter($arr, 'is_numeric') vs. > array_filter($arr, fn($x) => !is_numeric($x)); > > "Citation required" still stands in that case, but even if that function > call overhead does amount to 70% (and for inlined functions like is_numeric > it might), I would say that's not cause to add complexity to the filter > function, but rather cause to look at ways to optimize the code that exists > in the wild. It should be possible for the engine (at some layer) to look > at that closure and see that it's just negating some proxied call and elide > setting up the intermediate frame. Microoptimizations SHOULD be the > engine's job, not userspace's. > > -Sara >
  111742
August 31, 2020 16:00 pollita@php.net (Sara Golemon)
On Mon, Aug 31, 2020 at 10:35 AM David Rodrigues proweb@gmail.com>
wrote:
>> It should be possible for the engine (at some layer) to look at that closure
>> and see that it's just negating some proxied call and elide setting up the
>> intermediate frame. Microoptimizations SHOULD be the engine's job, not userspace's.
>> > > I really think that it should be a good solution, but how hard should it be to create a proxy like that?
>
We already have a few examples of proxies of this sort. Closure::fromCallable() comes to mind in particular. We could detect the `fn($x) => !y($x)` pattern and replace it with a callable of y with negation (and a few other common idioms). I wouldn't vote against a flag on array_filter(), because doing the quick and easy thing is very much in PHP's DNA, but I think we can cover a lot more ground with a more general purpose solution that leaves userspace to deal with bigger problems. -Sara
  111743
August 31, 2020 17:25 david.proweb@gmail.com (David Rodrigues)
> I wouldn't vote against a flag on array_filter(), because doing the quick and easy thing is very much in PHP's DNA, but I think we can cover a lot
more ground with a more general purpose solution that leaves userspace to deal with bigger problems. I totally agree with you. Atenciosamente, David Rodrigues Em seg., 31 de ago. de 2020 às 13:00, Sara Golemon <pollita@php.net> escreveu:
> On Mon, Aug 31, 2020 at 10:35 AM David Rodrigues proweb@gmail.com> > wrote: > >> It should be possible for the engine (at some layer) to look at that > closure > >> and see that it's just negating some proxied call and elide setting up > the > >> intermediate frame. Microoptimizations SHOULD be the engine's job, not > userspace's. > >> > > > > I really think that it should be a good solution, but how hard should it > be to create a proxy like that? > > > > We already have a few examples of proxies of this sort. > Closure::fromCallable() comes to mind in particular. We could detect the > `fn($x) => !y($x)` pattern and replace it with a callable of y with > negation (and a few other common idioms). > > I wouldn't vote against a flag on array_filter(), because doing the quick > and easy thing is very much in PHP's DNA, but I think we can cover a lot > more ground with a more general purpose solution that leaves userspace to > deal with bigger problems. > > -Sara >