I had a good conversation with @delacry over the library that was introduced .
And what struck me the most was the last example.
$topAdmins = $users
|> array_filter(?, fn(User $u) => $u->isActive())
|> array_map(fn(User $u) => $u->refresh(), ?)
|> array_filter(?, fn(User $u) => $u->isAdmin())
|> (fn($us) => (usort($us, fn(User $a, User $b) => $a->name <=> $b->name) ? $us : $us))
|> array_slice(?, 0, 10);
It is an example with the upcoming partial function application change (PHP 8.6).
I do agree, while it looks miles better than it is in PHP 8.5, it still is not that straight forward as the solutions with the builder pattern.
So I took a bit of time off from my dates project to come up with PAF. POAF looked weird to me, and PAF reminded me of a thing we said in Dutch when I was young, pief poef paf. So that is the whole story behind the name.
The example with the library looks like this.
$topadmins = $users
|> filterValues(?, fn(User $u) => $u->isActive())
|> mapSingle(?, fn(User $u) => $u->refresh())
|> filterValues(?, fn(User $u) => $u->isAdmin(), true)
|> sortValuesCustom(?, fn(User $a, User $b) => $a->name <=> $b->name)
|> array_slice(?, 0, 10);
Of course I'm biased, but I don't think anyone is going to say it looks worse.
Functions where the array is the first argument and return an array, like array_slice, don't need to be wrapped.
It is a bit more than a dumb wrapper for the array functions.
Another good point from the conversation was that array_filter leaves gaps in the keys. You could use array_values, but that only solves the problem for the integer keys. For string keys the solution is more complicated.
So I created a reIndex function that takes care of three cases:
- integers
- strings
- custom logic.
In the example you see that is triggered by adding true to the second use of the filterValues function in the chain.
I know using a boolean is controversial, but with named arguments you can do reIndex: true. I'm using them more and more, because they are code as documentation.
I went a bit overboard and I added the function to the map functions. The only use case I can think of at the moment, is using the custom logic to manipulate the keys before going to the next function in the chain.
It is still early days, and I already have a few other directions I want to take for the library. For example the sortValues and sortValuesCustom functions could be one.
It is a small library but I think it has enough value to make it a package. But it has a few more iterations to go before it is ready to be released.