Spaceship Operator

# 森建 (7 years ago)

PHP, Ruby, Groovy have spaceship operator <=>. In short, this operator compares values and returns 1, -1, 0.

ECMAScript spec's TypedArray#sort has the default comparison part like following code, so I think it's useful that appending spaceship operator to ECMAScript like it.
www.ecma-international.org/ecma-262/8.0/#sec-%typedarray%.prototype.sort

function isPlusZero(val) {
     return val === 0 && 1 / val === Infinity;
}

function defaultCompare(x, y) {
     const [isNaN_x, isNaN_y] = [Number.isNaN(x), Number.isNaN(y)];

     if(isNaN_x && isNaN_y)
         return 0;

     if(isNaN_x)
         return 1;

     if(isNaN_y)
         return -1;

     if(x < y)
         return -1;

     if(x > y)
         return 1;

     if(x === 0 && y === 0) {
         const [isPlusZero_x, isPlusZero_y] = [isPlusZero(x), isPlusZero(y)];

         if(!isPlusZero_x && isPlusZero_y)
             return -1;

         if(isPlusZero_x && !isPlusZero_y)
             return 1;
     }

     return 0;
}
// NaN behave like the biggest number
NaN <=> NaN // 0
NaN <=> 42 // 1
42 <=> NaN // -1
Infinity <=> NaN // -1

// finite
10 <=> 10 // 0
-1 <=> 10 // -1
10 <=> -1 // 1

// 0, -0 are not the same
-0 <=> 0 // -1
0 <=> -0 // 1

Use cases

// Array#sort can use TypedArray#sort default comparison part
[10, 5, NaN, -1].sort((a, b) => a <=> b); // [-1, 5, 10, NaN]

// desc order
new Float64Array([10, 5, NaN, -1]).sort((a, b) => -(a <=> b)); // [NaN, 10, 5, -1]

Problems

TypedArray#sort default comparison part has no string order function.

"abc" <=> "def" // same as "abc".localeCompare("def") ?
"abc" <=> 42 // same as "abc".localeCompare("42") ?

I found the reference to spaceship operator in ES Discuss. It has Already discussed in TC39 meeting?
esdiscuss.org/topic/informative-notes#content

# Isiah Meadows (7 years ago)

For what it's worth, for most practical purposes, `arr.sort((a, b) => b -

a))` works well enough. (The only thing it doesn't work well with are NaNs, but in practice, those almost never occur.)

# Mike Samuel (7 years ago)

On Tue, Jun 27, 2017 at 4:13 PM, Isiah Meadows <isiahmeadows at gmail.com> wrote:

For what it's worth, for most practical purposes, arr.sort((a, b) => b - a)) works well enough. (The only thing it doesn't work well with are NaNs, but in practice, those almost never occur.)

Don't numeric comparison operators typically sort -0 before +0?

((a,b)=>b-a) is also problematic for an array that contains two or

more infinite values with the same sign and one or more finite values since isNaN(Infinity-Infinity). That NaN from the comparator can be triggered or not based on details of the sorting algo and the precise placement on the Infinities.

# Isiah Meadows (7 years ago)

Inline

On Tue, Jun 27, 2017, 16:19 Mike Samuel <mikesamuel at gmail.com> wrote:

On Tue, Jun 27, 2017 at 4:13 PM, Isiah Meadows <isiahmeadows at gmail.com> wrote:

For what it's worth, for most practical purposes, arr.sort((a, b) => b - a)) works well enough. (The only thing it doesn't work well with are NaNs, but in practice, those almost never occur.)

Don't numeric comparison operators typically sort -0 before +0?

In JavaScript, not if I recall correctly. The only places where signed zeroes are relevant is in division.

((a,b)=>b-a) is also problematic for an array that contains two or more infinite values with the same sign and one or more finite values since isNaN(Infinity-Infinity). That NaN from the comparator can be triggered or not based on details of the sorting algo and the precise placement on the Infinities.

Infinities have also been similarly rare for me except in isolation.

# Mike Samuel (7 years ago)

On Tue, Jun 27, 2017 at 4:29 PM, Isiah Meadows <isiahmeadows at gmail.com> wrote:

Inline

On Tue, Jun 27, 2017, 16:19 Mike Samuel <mikesamuel at gmail.com> wrote:

On Tue, Jun 27, 2017 at 4:13 PM, Isiah Meadows <isiahmeadows at gmail.com> wrote:

For what it's worth, for most practical purposes, `arr.sort((a, b) => b

a))` works well enough. (The only thing it doesn't work well with are NaNs, but in practice, those almost never occur.)

Don't numeric comparison operators typically sort -0 before +0?

In JavaScript, not if I recall correctly. The only places where signed zeroes are relevant is in division.

There are others. Math.sign(-0)

((a,b)=>b-a) is also problematic for an array that contains two or more infinite values with the same sign and one or more finite values since isNaN(Infinity-Infinity). That NaN from the comparator can be triggered or not based on details of the sorting algo and the precise placement on the Infinities.

Infinities have also been similarly rare for me except in isolation.

Fair enough. There are more builtins that produce Infinity though. JSON.parse('1e1000')

# Claude Pache (7 years ago)

Le 27 juin 2017 à 22:19, Mike Samuel <mikesamuel at gmail.com> a écrit :

On Tue, Jun 27, 2017 at 4:13 PM, Isiah Meadows <isiahmeadows at gmail.com> wrote:

For what it's worth, for most practical purposes, arr.sort((a, b) => b - a)) works well enough. (The only thing it doesn't work well with are NaNs, but in practice, those almost never occur.)

Don't numeric comparison operators typically sort -0 before +0?

((a,b)=>b-a) is also problematic for an array that contains two or more infinite values with the same sign and one or more finite values since isNaN(Infinity-Infinity). That NaN from the comparator can be triggered or not based on details of the sorting algo and the precise placement on the Infinities.

When the comparison function produces NaN, it is treated the same way as 0; so no it is not a problem for infinities. More precisely, because (Infinity - Infinity) is NaN, Infinity is treated as “equal” to Infinity, which is correct.

It is an issue with NaN, because NaN will be treated as “equal” to any value.