Hi,
I found a problem with spaceship operator.
It doesn't define result for comparison with NaN.
$ sapi/cli/php -r 'var_dump(sqrt(-1) <=> 0);'
int(-1)
$ sapi/cli/php -r 'var_dump(0 <=> sqrt(-1));'
int(-1)
$ sapi/cli/php -r 'var_dump(0 < sqrt(-1));'
bool(false)
all other comparison operators return "false" as well.
Thanks. Dmitry.
As far as I know, we made it that way in order to enforce an int return type all the time.
int(-1) is indeed the sensible value for this. (Mainly int(0) does not work because it'd mean equality and so we're left with int(-1) and int(1).)
Just because other comparison ops already return a bool, we can return bool(false) there.
Bob
Am 15.06.2015 um 21:44 schrieb Dmitry Stogov dmitry@zend.com:
Hi,
I found a problem with spaceship operator.
It doesn't define result for comparison with NaN.$ sapi/cli/php -r 'var_dump(sqrt(-1) <=> 0);'
int(-1)
$ sapi/cli/php -r 'var_dump(0 <=> sqrt(-1));'
int(-1)$ sapi/cli/php -r 'var_dump(0 < sqrt(-1));'
bool(false)all other comparison operators return "false" as well.
Thanks. Dmitry.
-----Original Message-----
From: Bob Weinand [mailto:bobwei9@hotmail.com]
Sent: Monday, June 15, 2015 9:55 PM
To: Dmitry Stogov
Cc: davey@php.net; Andrea Faulds; Stanislav Malyshev; Anatol Belski; Kalle
Sommer Nielsen; PHP Internals
Subject: Re: [PHP-DEV] Spaceship and NaNsAs far as I know, we made it that way in order to enforce an int return
type all
the time.
int(-1) is indeed the sensible value for this. (Mainly int(0) does not
work because
it'd mean equality and so we're left with int(-1) and int(1).)Just because other comparison ops already return a bool, we can return
bool(false) there.Bob
Am 15.06.2015 um 21:44 schrieb Dmitry Stogov dmitry@zend.com:
Hi,
I found a problem with spaceship operator.
It doesn't define result for comparison with NaN.$ sapi/cli/php -r 'var_dump(sqrt(-1) <=> 0);'
int(-1)
$ sapi/cli/php -r 'var_dump(0 <=> sqrt(-1));'
int(-1)$ sapi/cli/php -r 'var_dump(0 < sqrt(-1));'
bool(false)all other comparison operators return "false" as well.
false were correct, IMHO. Btw looks like the same case is with NAN
<=> NAN.
Regards
Anatol
As far as I know, we made it that way in order to enforce an int return
type all the time.
int(-1) is indeed the sensible value for this. (Mainly int(0) does not
work because it'd mean equality and so we're left with int(-1) and
int(1).)Just because other comparison ops already return a bool, we can return
bool(false) there.
This makes a lot of sense. If it returned false, that would just be cast to 0 in most situations, implying that NaN is equal to everything (rather than nothing). In other situations, it would simply lead to an error. The operator would lose much of its value if it had to be surrounded with error traps and caveats because it didn't reliably return an integer.
Regards,
Rowan Collins
[IMSoP]
On Mon, Jun 15, 2015 at 4:45 PM, Rowan Collins rowan.collins@gmail.com
wrote:
As far as I know, we made it that way in order to enforce an int return
type all the time.
int(-1) is indeed the sensible value for this. (Mainly int(0) does not
work because it'd mean equality and so we're left with int(-1) and
int(1).)Just because other comparison ops already return a bool, we can return
bool(false) there.This makes a lot of sense. If it returned false, that would just be cast
to 0 in most situations, implying that NaN is equal to everything (rather
than nothing). In other situations, it would simply lead to an error. The
operator would lose much of its value if it had to be surrounded with error
traps and caveats because it didn't reliably return an integer.
Convenience aside, I think it has to be false, or an ERROR, or something
other than int.
Clause 5.11, paragraph 2 of the 754-2008 standard reads:
Four mutually exclusive relations are possible: less than, equal, greater
than, and unordered. The last case arises when at least one operand is NaN.
Every NaN shall compare unordered with everything, including itself.
Personally, I'd vote false for consistency and immediacy. Then, I'd
suggest we look at handling NaN more predictably. Pretty much whenever NaN
enters as a data point, the end result will be NaN, and I want to know that
as early as possible. Like an ERROR.
bishop
Hi!
Just because other comparison ops already return a bool, we can return
bool(false) there.
But we can not return bool from operator that is declared as returning
int, and adding extra type would make this operator essentially useless,
as it is meant to be a concise way of comparing two things, and if after
that you need to write a parser to figure out what it returned, it's
much easier to just go back to basic comparison operators.
Since not everything among PHP values is well-ordered, there would be
sets of values for which comparison does not make intuitive sense - i.e.
both < and > are false, etc. In this case, there is no intuitive value
to return, but there should be a well-defined one to return, and we have
a pretty good definition here I think:
https://github.com/php/php-langspec/blob/master/spec/10-expressions.md#relational-operators
Stas Malyshev
smalyshev@gmail.com
Hi!
I found a problem with spaceship operator.
It doesn't define result for comparison with NaN.$ sapi/cli/php -r 'var_dump(sqrt(-1) <=> 0);'
int(-1)
$ sapi/cli/php -r 'var_dump(0 <=> sqrt(-1));'
int(-1)$ sapi/cli/php -r 'var_dump(0 < sqrt(-1));'
bool(false)all other comparison operators return "false" as well.
I think <=> is defined as:
- if < returns true, then negative
- if == returns true, then 0
- otherwise, positive
https://github.com/php/php-langspec/blob/master/spec/10-expressions.md#relational-operators
So the result here is wrong I assume. I suspect this is the consequence
of how compare_function treats IS_DOUBLE - it first subtracts them
(which produces NaN) and then does ZEND_NORMALIZE_BOOL - which is:
#define ZEND_NORMALIZE_BOOL(n)
((n) ? (((n)>0) ? 1 : -1) : 0)
Since NaN > 0 is false, what we get is -1. I guess we should add check
for NaN in either ZEND_NORMALIZE_BOOL or comparison routine, but not
sure what comparing to NaN should produce... Always false? AFAIK NaN is
not equal to NaN so that may be the best option.
The individual comparison operators already return false with NaN but I
suspect not for the right reasons...
Stas Malyshev
smalyshev@gmail.com