|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2012-07-17 19:56 UTC] fabien dot delorme at gmail dot com
Description:
------------
The documentation for usort function (and, it seems, other relative functions,
although I haven't tested all of them) is slightly wrong regarding the callback
function. It says :
"The comparison function must return an integer less than, equal to, or greater
than zero if the first argument is considered to be respectively less than, equal
to, or greater than the second."
However it sometimes results in wrong results if the return value is not
precisely -1, 0 or 1. For example, returning $arg2 - $arg1 won't always perform
the correct operation.
Even if PHP builtin comparison functions all have this behavior (returning
precisely -1, 0 or 1), this is not necessarily the case for user-defined functions
and either code or documentation should be clear about what values shall be
returned.
Test script:
---------------
$a=array(15.44, 5.76, 10.43, 6.12, 6.17, 7.21, 8.62, 8.91);
usort($a, function($x, $y) {return $y - $x; });
var_dump($a);
// The above would work if the lambda was something like
// function($x, $y) { return $x == $y ? 0 : ($x < $y ? -1 : 1);}
Expected result:
----------------
array(8) {
[0]=>
float(15.44)
[1]=>
float(10.43)
[2]=>
float(8.91)
[3]=>
float(8.62)
[4]=>
float(7.21)
[5]=>
float(6.17)
[6]=>
float(6.12)
[7]=>
float(5.76)
}
Actual result:
--------------
array(8) {
[0]=>
float(15.44)
[1]=>
float(10.43)
[2]=>
float(8.62)
[3]=>
float(8.91)
[4]=>
float(7.21)
[5]=>
float(6.12)
[6]=>
float(5.76)
[7]=>
float(6.17)
}
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2026 The PHP GroupAll rights reserved. |
Last updated: Wed Oct 07 22:00:01 2026 UTC |
The custom callback function should return an integer value either less-than, greater-than, or equal to zero. For less than, greater than, and equal comparison respectively. The documentation is really wrong here as it does explicitly state "an integer". The code in this example is clearly return floating point numbers. What happens is that the last two values in this array (6.17 and 5.76): Actual result: -------------- array(8) { [0]=> float(15.44) [1]=> float(10.43) [2]=> float(8.62) [3]=> float(8.91) [4]=> float(7.21) [5]=> float(6.12) [6]=> float(5.76) [7]=> float(6.17) } are both cast to integer values behind the scenes (from array.c line 592): long retval; convert_to_long_ex(&retval_ptr); retval = Z_LVAL_P(retval_ptr); zval_ptr_dtor(&retval_ptr); return retval < 0 ? -1 : retval > 0 ? 1 : 0; As you can see the comparison is quite similar to the proposed "return $x == $y ? 0 : ($x < $y ? -1 : 1);" you included here. What is really expected here is ($comparison > 0 || $comparison < 0 || $compirson == 0). I will try to make the documentation more clear about this where possible, but for now this is not concerned a documentation bug. I can appreciate a need for further clarification where subtle details may not be too obvious at first.