<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Mar 24, 2010, at 2:31 PM, Alexander Belopolsky wrote:</div><br><blockquote type="cite"><div>"""<br>In this context it doesn't particularly shock me that operations on<br>NaN should cause invariant violations. After all, isn't NaN supposed<br>to mean "not a number"? If it's not a number, it doesn't have to<br>satisfy the properties of numbers.<br>"""<br></div></blockquote><div><br></div><div><div>This sound like a good, universal reply to "bug reports" about</div><div>various containers/tools not working with NaNs :-)</div><div><br></div><div>Bug report: "Container X or Function Y doesn't behave well when I</div><div>give it a NaN as an input".</div><div><br></div><div>Closed -- Won't fix: &nbsp;"It does not shock me that a NaN violates that</div><div>tool or container's invariants."</div></div><div><br></div><blockquote type="cite"><div><br>To bring the discussion back on topic for python-dev, I would argue<br>that reflexivity should hold for hashable values. &nbsp;Having it otherwise<br>would lead to unsurmountable problems when storing such values in sets<br>or using them as keys in dictionaries. &nbsp;If x == x is False stays for x<br>= float('nan'), I would argue that hash(float('nan')) should raise<br>NotImplemented or ValueError.</div></blockquote><br></div><div>Hashability isn't the only place where you have a problem.</div><div>Even unordered collections are affected:</div><div><br></div><div>&nbsp;&nbsp;&gt;&gt;&gt; class ListBasedSet(collections.Set):</div><div>&nbsp;&nbsp; &nbsp; ''' Alternate set implementation favoring space over speed</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; and not requiring the set elements to be hashable. '''</div><div>&nbsp;&nbsp; &nbsp; def __init__(self, iterable):</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; self.elements = lst = []</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; for value in iterable:</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if value not in lst:</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lst.append(value)</div><div>&nbsp;&nbsp; &nbsp; def __iter__(self):</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; return iter(self.elements)</div><div>&nbsp;&nbsp; &nbsp; def __contains__(self, value):</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; return any(value == elem for elem in self.elements)</div><div>&nbsp;&nbsp; &nbsp; def __len__(self):</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; return len(self.elements)</div><div><br></div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</div><div>&gt;&gt;&gt; n = float('Nan')</div><div>&gt;&gt;&gt; s = ListBasedSet([n])</div><div>&gt;&gt;&gt; n in s &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # unexpected result</div><div>False</div><div><div>&gt;&gt;&gt; len(s) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# expected result</div><div>1</div></div><div>&gt;&gt;&gt; len(s &amp; s) &nbsp; &nbsp; &nbsp; &nbsp; # unexpected result</div><div>0</div><br><div>If we want to be able to reason about our programs,</div><div>then we need to rely on equality relations being</div><div>reflexsive, symmetric, and transitive. &nbsp;Otherwise,</div><div>containers and functions can't even make minimal&nbsp;</div><div>guarantees&nbsp;about what they do.</div><div><br></div><div>Anything else smells of a Douglas Hofstadter style</div><div>or Betrand Russell style logic bomb:</div><div><br></div><div>* this sentence is a lie</div><div>* this object isn't equal to itself</div><div>* this is&nbsp;<span class="Apple-style-span" style="font-family: sans-serif; font-size: 13px; line-height: 19px; ">a set containing sets that are not members of themselves</span></div><div><font class="Apple-style-span" face="sans-serif" size="3"><span class="Apple-style-span" style="font-size: 13px; line-height: 19px;"><i><br></i></span></font></div><div><font class="Apple-style-span" face="sans-serif" size="3"><span class="Apple-style-span" style="font-size: 13px; line-height: 19px;">The property of NaN objects not being equal to themselves</span></font></div><div><font class="Apple-style-span" face="sans-serif" size="3"><span class="Apple-style-span" style="font-size: 13px; line-height: 19px;">is more harmful than helpful. &nbsp;We should probably draw the</span></font></div><div><font class="Apple-style-span" face="sans-serif" size="3"><span class="Apple-style-span" style="font-size: 13px; line-height: 19px;">line at well-defined numeric contexts such as the decimal module</span></font></div><div><font class="Apple-style-span" face="sans-serif" size="3"><span class="Apple-style-span" style="font-size: 13px; line-height: 19px;">and stop trying to propagate NaN awareness throughout the</span></font></div><div><font class="Apple-style-span" face="sans-serif" size="3"><span class="Apple-style-span" style="font-size: 13px; line-height: 19px;">entire object model.</span></font></div><div><font class="Apple-style-span" face="sans-serif" size="3"><span class="Apple-style-span" style="font-size: 13px; line-height: 19px;"><br></span></font></div><div><font class="Apple-style-span" face="sans-serif" size="3"><span class="Apple-style-span" style="font-size: 13px; line-height: 19px;"><br></span></font></div><div><font class="Apple-style-span" face="sans-serif" size="3"><span class="Apple-style-span" style="font-size: 13px; line-height: 19px;">Raymond</span></font></div><div><br></div></body></html>