<html><head><meta http-equiv="Content-Type" content="text/html charset=iso-8859-1"><meta http-equiv="Content-Type" content="text/html charset=iso-8859-1"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><br><div><div>On Jul 7, 2014, at 4:37 PM, Andreas Maier <<a href="mailto:andreas.r.maier@gmx.de">andreas.r.maier@gmx.de</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><span style="font-family: ArialMT; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); float: none; display: inline !important;">I do not really buy into the arguments that try to show how identity and value are somehow the same. They are not, not even in Python.</span><br style="font-family: ArialMT; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><br style="font-family: ArialMT; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-family: ArialMT; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); float: none; display: inline !important;">The argument I can absolutely buy into is that the implementation cannot be changed within a major release. So the real question is how we document it.</span></blockquote></div><br><div><div>Once every few years, someone discovers IEEE-754, learns that NaNs</div><div>aren't supposed to be equal to themselves and becomes inspired</div><div>to open an old debate about whether the wreck Python in a effort</div><div>to make the world safe for NaNs.  And somewhere along the way,</div><div>people forget that practicality beats purity.</div><div><br></div><div>Here are a few thoughts on the subject that may or may not add</div><div>a little clarity ;-)</div><div><br></div><div>* Python already has IEEE-754 compliant NaNs:</div><div><br></div><div>       assert float('NaN') != float('NaN')</div><div><br></div><div>* Python already has the ability to filter-out NaNs:</div><div><br></div><div>       [x for x in container if not math.nan(x)]</div><div><br></div><div>* In the numeric world, the most common use of NaNs is for</div><div>  missing data (much like we usually use None).  The property</div><div>  of not being equality to itself is primarily useful in</div><div>  low level code optimized to run a calculation to completion</div><div>  without running frequent checks for invalid results</div><div>  (much like @n/a is used in MS Excel).</div><div><br></div><div>* Python also lets containers establish their own invariants</div><div>  to establish correctness, improve performance, and make it</div><div>  possible to reason about our programs:</div><div><br></div><div>           for x in c:</div><div><span class="Apple-tab-span" style="white-space:pre">     </span>       assert x in c</div></div><div><br></div><div><div>* Containers like dicts and sets have always used the rule</div><div>  that identity-implies equality.  That is central to their</div><div>  implementation.  In particular, the check of interned</div><div>  string keys relies on identity to bypass a slow</div><div>  character-by-character comparison to verify equality.</div><div><br></div><div>* Traditionally, a relation R is considered an equality</div><div>  relation if it is reflexive, symmetric, and transitive:</div><div><br></div><div>      R(x, x) -> True</div><div>      R(x, y) -> R(y, x)</div><div>      R(x, y) ^ R(y, z) -> R(x, z)</div><div><br></div><div>* Knowingly or not, programs tend to assume that all of those</div><div>  hold.  Test suites in particular assume that if you put</div><div>  something in a container that assertIn() will pass.</div><div><br></div><div>* Here are some examples of cases where non-reflexive objects</div><div>  would jeopardize the pragmatism of being able to reason</div><div>  about the correctness of programs:</div><div><br></div><div>      s = SomeSet()</div><div>      s.add(x)</div><div>      assert x in s</div><div><br></div><div>      s.remove(x)        # See collections.abc.Set.remove</div><div>      assert not s</div><div><br></div><div>      s.clear()          # See collections.abc.Set.clear</div><div>      asset not s</div><div><br></div><div>* What the above code does is up to the implementer of the</div><div>  container.  If you use the Set ABC, you can choose to</div><div>  implement __contains__() and discard() to use straight</div><div>  equality or identity-implies equality.  Nothing prevents</div><div>  you from making containers that are hard to reason about.</div><div><br></div><div>* The builtin containers make the choice for identity-implies</div><div>  equality so that it is easier to build fast, correct code.</div><div>  For the most part, this has worked out great (dictionaries</div><div>  in particular have had identify checks built-in from almost</div><div>  twenty years).</div></div><div><br></div><div><div>* Years ago, there was a debate about whether to add an __is__()</div><div>  method to allow overriding the is-operator.  The push for the</div><div>  change was the "pure" notion that "all operators should be</div><div>  customizable".  However, the idea was rejected based on the</div><div>  "practical" notions that it would wreck our ability to reason</div><div>  about code, it slow down all code that used identity checks,</div><div>  that library modules (ours and third-party) already made</div><div>  deep assumptions about what "is" means, and that people would</div><div>  shoot themselves in the foot with hard to find bugs.</div><div><br></div><div>Personally, I see no need to make the same mistake by removing</div><div>the identity-implies-equality rule from the built-in containers.</div><div>There's no need to upset the apple cart for nearly zero benefit.</div></div><div><br></div><div>IMO, the proposed quest for purity is misguided.</div><div>There are many practical reasons to let the builtin</div><div>containers continue work as the do now.</div><div><br></div><div><br></div><div>Raymond </div></body></html>