On Dec 29, 2019, at 04:34, Steven D'Aprano <st...@pearwood.info> wrote:
> 
> On Sat, Dec 28, 2019 at 11:58:35PM -0800, Andrew Barnert via Python-ideas 
> wrote:
> 
>> No it won’t, unless you assume here that no possible non-numeric types 
>> could ever have non-self-equal values. Which isn’t true.
> 
> Reflexivity of equality (namely, that any value should be equal to 
> itself) is such a fundamental property that I would assume that NANs are 
> the only exception, until such time as somebody points out an 
> uncontrived real-world example.

It may be a fundamental property in math, and in many other programming 
languages, but not in Python (and many other programming languages).

Numpy arrays: a==a is neither true nor false, but a bool array the same shape 
as a (which will raise if used in an if statement or otherwise converted to 
bool).

sNaN: Adding special handling for Decimal won’t help any third-party libs that 
also do sNaN properly and raise instead of returning false from a==a.

ORMs: a==a is neither true nor false, it’s a where clause that, when used to 
form a query, compared column a to itself, but it has no bool value.

SymPy: a==a is neither true nor false, it’s the equation a==a.

Other libraries that build other things out of expressions are similar to the 
ORM and SymPy cases.

Not-a-Time values from various date time libraries: a==a is false, but the type 
is not a numeric type in the first place.

Meanwhile, are there any non-contrived types for which the equals test does the 
right thing? Sure. Quiet NaN-like values from third-party number libraries. But 
does using == to get the right answer for qNaN from those types, even though it 
means we get the wrong answer for sNaN from those same types, not to mention 
all kinds of other types, actually make the function more generic, or more 
useful than one that just raised for types it wasn’t prepared to deal with? 
Certainly not in general. Maybe for some specific use it does, but without 
knowing what the intended use of a “generic isnan” function is (which I’ve 
asked for three times now—the statistics module doesn’t seem to need one given 
that it’s intentionally not generic), all you have is that it might be useful 
in some use that nobody’s come up with where you want to duck-type NaN-ness and 
don’t care that it often does the wrong thing but do care that it does the 
right thing for some particular case that wouldn’t otherwise be handled.

> A bigger concern is the question of what should isnan do for non-numeric 
> types?
> 
>    isnan(None)
>    # raise or return False?
> 
> Clearly None is not a NAN, so it shouldn't return True. Should it return 
> False because its not a NAN, or raise because it's not a numeric type at 
> all?

I think it should raise an exception, just as I said a paragraph later for 
strings. Returning true implies that it’s a NaN, returning false implies that 
it’s not not a number, and both are wrong.

Consider this: what should isfinite or isinfinite or ispositive do for None or 
a string? If they should raise, why should isnan be different?

A better question is, what should a numpy array do? Numpy’s own isnan returns a 
bool array of the same shape, just like comparisons do. But is that what we 
want? Or do we want to treat scalars (0D arrays) special? Or do we want to ask 
numpy to try to convert to a scalar (in which case it’ll treat all 1-element 
arrays of any dimension special)? Or …?

Similarly, should an expression library be able to capture the isnan test and 
turn it into part of the query or equation or whatever it is that it’s 
building, or should it raise?

The advantage of using an isnan method or an __isnan__ protocol, and then 
raising for anything else (maybe with special exceptions for the builtin number 
types), instead of trying to come up with something that sort of works for all 
types, is that numpy and expression libraries and so on get to make that 
decision, instead of the statistics module or the math module or wherever this 
is intended to go.

_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/RPS3AF3Q7XCC2HSIFFM3UI6PEMCCI6N7/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to