array_reject() as counterpart of array_filter()

php.internals

David Rodrigues

6 years ago
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().

Larry Garfield

6 years ago
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

Josh Bruce

6 years ago
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

Chase Peeler

6 years ago
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

David Rodrigues

6 years ago
> 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:

Sara Golemon

6 years ago
On Mon, Aug 31, 2020 at 9:41 AM David Rodrigues <david.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

David Rodrigues

6 years ago
> 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:

Sara Golemon

6 years ago
On Mon, Aug 31, 2020 at 10:35 AM David Rodrigues <david.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

David Rodrigues

6 years ago
> 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: