php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #62590 usort & al : documentation about callback is wrong
Submitted: 2012-07-17 19:56 UTC Modified: 2012-07-20 02:36 UTC
Votes:1
Avg. Score:3.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (100.0%)
From: fabien dot delorme at gmail dot com Assigned: googleguy (profile)
Status: Closed Package: Documentation problem
PHP Version: 5.3.14 OS: MacOS lion
Private report: No CVE-ID: None
 [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)
}

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-07-20 00:39 UTC] googleguy@php.net
-Assigned To: +Assigned To: googleguy
 [2012-07-20 01:00 UTC] googleguy@php.net
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.
 [2012-07-20 01:03 UTC] googleguy@php.net
I forget to add that the after the last few values in the resulting array are 
computed their differences come out to -0.36, 0.41, and 0.05. So as you can see a 
cast of these values to (int) all result in 0 making the comparison a wash and 
the documentation notes that values compared as equal will have an undefined 
order, which is why the order of the last three elements there doesn't seem make 
any sense.
 [2012-07-20 02:22 UTC] googleguy@php.net
Automatic comment from SVN on behalf of googleguy
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=326718
Log: Added caution for returning non-integer types to help clarify language for usort callback behavior.
Address issues raised in Bug #62590
 [2012-07-20 02:36 UTC] googleguy@php.net
-Status: Assigned +Status: Closed
 [2012-07-20 02:36 UTC] googleguy@php.net
This bug has been fixed in the documentation's XML sources. Since the
online and downloadable versions of the documentation need some time
to get updated, we would like to ask you to be a bit patient.

Thank you for the report, and for helping us make our documentation better.


 
PHP Copyright © 2001-2026 The PHP Group
All rights reserved.
Last updated: Wed Oct 07 22:00:01 2026 UTC