On 2024-10-21 06:42, Gina P. Banyard wrote:
Hello internals,
I would like to propose a short RFC to make the return value of the sort() and
similar functions more useful:
https://wiki.php.net/rfc/array-sort-return-array
I intend for the discussion to last 2 weeks and then open the vote.
Best regards,
Gina P. Banyard
I've been working up something very much similar so I'd be well behind this.
My thinking ended up the same as Larry Garfield's:
> *sorted($arr) seems like it would be a lot less confusing, and
consistent with what other languages (and hopefully future PHP) do. (I
don't know what that means for array_walk(), but I don't know what that
would even return anyway.)
Making it a new function instead of changing the existing function would
be less of a break it seems.
Excerpts from my drafts:
All of the functions [the thirteen array sorting functions, including
shuffle()] have the less-than-informative return type of `true` (except
`array_multisort()` with its more complex argument requirements and
hence the ability to also return `false`). All of their behaviour is by
reference. Oh, except when they flat-out fail, in which case they return
null.
This means that if you want to sort an array you have to have an entire
statement devoted to the task. As an expression, `sort()` just doesn’t
compose: you can’t sensibly use it anywhere as part of a larger expression.
You have to write:
$escaped = $array->valued($expression);
sort($escaped);
$escaped = array_map(escape(...), $escaped);
because
$escaped = array_map(escape(...), sort($array->valued($expression));
simply won’t work.
It gets in the way when using it as a callback in array functions. You
can’t use:
$sorted_datasets = array_map(sort(...), $datasets);
You want
$sorted_datasets = $datasets;
array_walk($sorted_datasets, sort(...));
`array_walk()` is the only built-in array function using callbacks that
can meaningfully accept `sort()` (even the `array_walk_recursive()`
variant will recurse into child arrays instead of sorting them). Because
`array_walk()` iterates through the array by reference as well, it too
interrupts functional composition, as just shown above. But at least it
can often be replaced by `array_map()` (just look at the number of user
notes on its manual page that suggest using references to make it behave
more that way). `array_walk()` is basically for the case where there is
no useful value to return from traversing the array (good thing, too,
since its return type is `true`). But I digress.
...
The name `sorted()` has already been introduced. The `-ed` suffix can be
grammatically applied to all of the sorting functions (technically for
`shuffle()` the suffix would be `-d` because the `e` is already there).
But that is just the one I came up with.
What we don’t want is Yet Another Prefix to go into the alphabet soup
that is `([ak]?r?|u[ak]?|nat(case)?)`. “Hey, how about we use ‘f’ as a
prefix meaning ‘functional’?” “Do you want to be responsible for
prefixing ‘uksort’ with an ‘f’?”
At the same time we don’t want any modification that would make the name
clunky to use. Not everything should be reliant on IDE autocompletion.
...
Most languages in widespread use do operate on their arrays in place,
but in those cases the arrays are object types and sorting is an
instance method performed on and modifying the object. That’s not how
PHP models arrays. Functional languages meanwhile have – by definition –
functional sort functions.
One notable example is Python, in which lists have an in-place `.sort()`
method. The language however also offers a global `sorted()` function,
which takes a list and returns a new, sorted one, pretty much like what
is proposed here, and for pretty much the same reason: it is more easily
composable with other operations.
...
It would impact anyone (such as myself) who already defines global
functions named `sorted()`. In my case it’s precisely so that I can have
such functional sort functions. It’s not unlikely that there are
functions with that name that have other jobs (e.g. a `sorted` that
tests whether a list is sorted) and would need to be renamed (e.g. to
`is_sorted`). But adding any functions to core would mean renaming
existing global user functions that currently have the same names
regardless of what they are for. A quick github search turned up a
number of `sorted` global functions, some of them exactly matching the
userland implementation above; and all (from the sample I took) looking
like the intent is to take an array (by value) or something that is
queried for an array, sort it in some way, and return the result. In
other words, passing the array to be sorted by value and returning the
sorted array is the more common idiom.
[The userland implementation mentioned being
function sorted(array $array): array
{
sort($array);
return $array;
}
]