Spaceship Operator

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Spaceship Operator

森建
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.
<a href="http://www.ecma-international.org/ecma-262/8.0/#sec-%typedarray%.prototype.sort">http://www.ecma-international.org/ecma-262/8.0/#sec-%typedarray%.prototype.sort

```javascript
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;
}
```

```javascript
// 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

```javascript
// 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.

```javascript
"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?
https://esdiscuss.org/topic/informative-notes#content-3
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Spaceship Operator

Isiah Meadows-2

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.)


On Tue, Jun 27, 2017, 16:11 森建 <[hidden email]> wrote:
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.
<a href="http://www.ecma-international.org/ecma-262/8.0/#sec-%typedarray%.prototype.sort" rel="noreferrer" target="_blank">http://www.ecma-international.org/ecma-262/8.0/#sec-%typedarray%.prototype.sort

```javascript
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;
}
```

```javascript
// 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

```javascript
// 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.

```javascript
"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?
https://esdiscuss.org/topic/informative-notes#content-3
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Spaceship Operator

Mike Samuel
On Tue, Jun 27, 2017 at 4:13 PM, Isiah Meadows <[hidden email]> 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.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Spaceship Operator

Isiah Meadows-2
Inline 

On Tue, Jun 27, 2017, 16:19 Mike Samuel <[hidden email]> wrote:
On Tue, Jun 27, 2017 at 4:13 PM, Isiah Meadows <[hidden email]> 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. 

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Spaceship Operator

Mike Samuel
On Tue, Jun 27, 2017 at 4:29 PM, Isiah Meadows <[hidden email]> wrote:

> Inline
>
> On Tue, Jun 27, 2017, 16:19 Mike Samuel <[hidden email]> wrote:
>>
>> On Tue, Jun 27, 2017 at 4:13 PM, Isiah Meadows <[hidden email]>
>> 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')
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Spaceship Operator

Claude Pache
In reply to this post by Mike Samuel

> Le 27 juin 2017 à 22:19, Mike Samuel <[hidden email]> a écrit :
>
> On Tue, Jun 27, 2017 at 4:13 PM, Isiah Meadows <[hidden email]> 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.

—Claude

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Loading...