On Wed, Mar 4, 2020 at 11:12 PM Christoph M. Becker <cmbecke...@gmx.de> wrote:
> On 04.03.2020 at 19:11, Nikita Popov wrote: > > > 1. As Tyson suggests, we can throw a warning if a boolean is returned > from > > the comparison callback (probably with a check to only throw it once per > > sort), to make it obvious what the cause is. > > > > 2. We can fix this transparently by doing something like this internally: > > > > $result = $compare($a, $b); > > if ($result !== false) { > > return (int) $result; // Normal behavior > > } > > > > // Bad comparison function, try the reverse order as well > > return -$compare($b, $a); > > > > That is, we will recover the full three-way comparison result from the > > "greater than" result, by checking for both $a > $b and $b > $a. > > Given that we have internal classes which deliberately have such > comparison behavior (i.e. returning 0 or 1, to signal that there is no > order defined), e.g. Closures[1], I tend to prefer raising a warning > instead of trying to recover. > > [1] > <https://github.com/php/php-src/blob/php-7.4.3/Zend/zend_closures.c#L372> > This is a different case. The problem with my example is that it reports equality where none exists, which is an issue if you try to change the ordering of equal elements. Your case (which is indeed somewhat common in extension code) always returns "greater-than" for non-equal elements. The end result here is that the sort will not have any defined order regardless of how we perform it. We can't really do anything about such cases. I expect that a proposal for userland compare and equality overloading may want to make the "not ordered" case more explicit, in which case we could throw a warning when such comparisons are performed as part of sorting. Nikita