File 3231-otp-Explain-the-term-equivalence-operators.patch of Package erlang

From 6498901fe251507bc6576d673071b38e1b4e9168 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org>
Date: Fri, 11 Aug 2023 10:36:46 +0200
Subject: [PATCH 1/2] otp: Explain the term equivalence operators

---
 system/doc/reference_manual/data_types.xml  | 31 ++++++++++++
 system/doc/reference_manual/expressions.xml | 54 ++++++++++++++++++---
 2 files changed, 78 insertions(+), 7 deletions(-)

diff --git a/system/doc/reference_manual/data_types.xml b/system/doc/reference_manual/data_types.xml
index 4b58c6a5ca..0fd65c43f5 100644
--- a/system/doc/reference_manual/data_types.xml
+++ b/system/doc/reference_manual/data_types.xml
@@ -87,6 +87,37 @@
 11> <input>1_234.333_333</input>
 1234.333333
 </pre>
+<marker id="numeric_comparisons" />
+    <section>
+      <title>Comparisons</title>
+      <p>Both integers and floats share the same linear order. That is,
+        <c>1</c> compares less than <c>2.4</c>, <c>3</c> compares greater than
+        <c>2.99999</c>, and <c>5</c> is equal to <c>5.0</c>.</p>
+      <p>When wanting to compare an integer with another integer or a float
+        with another float, it may be tempting to use the term equivalence
+        operators (<c>=:=</c>, <c>=/=</c>) or pattern matching. This works for
+        integers which has a distinct representation for every number, but
+        there's a surprising edge case for floating-point as the latter has two
+        representations for zero which are considered different by the term
+        equivalence operators and pattern matching.</p>
+      <p>If you wish to compare floating-point numbers <em>numerically</em>,
+        use the regular comparison operators (such as <c>==</c>) and add guards
+        that require both the arguments to be floating-point.</p>
+      <note>
+        <p>Prior to OTP 27, the term equivalence operators had a bug where they
+          considered <c>0.0</c> and <c>-0.0</c> to be the same term. Legacy
+          code that makes equality comparisons on floating-point zero should
+          migrate to using the equal-to (<c>==</c>) operator with
+          <c>is_float/1</c> guards, and compiler warnings have been added to
+          that effect. These can be silenced by writing <c>+0.0</c> instead,
+          which is the same as <c>0.0</c> but makes the compiler interpret the
+          comparison as being purposely made against <c>0.0</c>.</p>
+        <p>Note that this does <em>not</em> break compatibility with IEEE 754
+          which mandates that <c>0.0</c> and <c>-0.0</c> should compare
+          equal: they are equal when interpreted as numbers (<c>==</c>), and
+          unequal when interpreted as opaque terms (<c>=:=</c>).</p>
+      </note>
+    </section>
 <marker id="float_representation_problem" />
     <section>
       <title>Representation of Floating Point Numbers</title>
diff --git a/system/doc/reference_manual/expressions.xml b/system/doc/reference_manual/expressions.xml
index 6b3ba96b6b..77f46d5363 100644
--- a/system/doc/reference_manual/expressions.xml
+++ b/system/doc/reference_manual/expressions.xml
@@ -801,11 +801,11 @@ Expr1 <input>op</input> Expr2</pre>
       </row>
       <row>
         <cell align="left" valign="middle">=:=</cell>
-        <cell align="left" valign="middle">Exactly equal to</cell>
+        <cell align="left" valign="middle">Term equivalence</cell>
       </row>
       <row>
         <cell align="left" valign="middle">=/=</cell>
-        <cell align="left" valign="middle">Exactly not equal to</cell>
+        <cell align="left" valign="middle">Term non-equivalence</cell>
       </row>
       <tcaption>Term Comparison Operators.</tcaption>
     </table>
@@ -836,6 +836,28 @@ number &lt; atom &lt; reference &lt; fun &lt; port &lt; pid &lt; tuple &lt; map
       depending on the size of the float because otherwise comparison of large
       floats and integers would lose their transitivity.</p>
 
+    <p>The term equivalence operators, <c>=:=</c> and <c>=/=</c>, return
+      whether two terms are indistinguishable. While the other operators
+      consider the same <em>numbers</em> equal even when their types differ
+      (<c>1 == 1.0</c> is true), the term equivalence operators return whether
+      there exists any function that can tell their arguments apart.</p>
+
+    <p>For example, while the terms <c>0</c> and <c>0.0</c> represent the same
+      <em>number</em>, we can tell them apart by using the <c>is_integer/1</c>
+      function. Hence, <c>=:=</c> and <c>=/=</c> consider them different.</p>
+
+    <p>Furthermore, the terms <c>0.0</c> and <c>-0.0</c> also represent the
+      same <em>number</em>, but they yield different results when converted to
+      string form through <c>float_to_list/1</c>: when given the former it
+      returns a string without a sign, and when given the latter it returns a
+      string with a sign. Therefore, <c>=:=</c> and <c>=/=</c> consider
+      them different.</p>
+
+    <p>The term equivalence operators are useful when reasoning about terms as 
+      opaque values, for example in associative containers or memoized
+      functions where using the equal-to operator (<c>==</c>) can result in
+      subtly incorrect results.</p>
+
     <p>Term comparison operators return the Boolean value of the
       expression, <c>true</c> or <c>false</c>.</p>
 
@@ -845,17 +867,35 @@ number &lt; atom &lt; reference &lt; fun &lt; port &lt; pid &lt; tuple &lt; map
 true
 2> <input>1=:=1.0.</input>
 false
-3> <input>1 > a.</input>
+3> <input>0=:=0.0.</input>
 false
-4> <input>#{c => 3} > #{a => 1, b => 2}.</input>
+4> <input>0.0=:=-0.0.</input>
 false
-5> <input>#{a => 1, b => 2} == #{a => 1.0, b => 2.0}.</input>
+5> <input>0.0=:=+0.0.</input>
 true
-6> <input>&lt;&lt;2:2>> &lt; &lt;&lt;128>>.</input>
+6> <input>1 > a.</input>
+false
+7> <input>#{c => 3} > #{a => 1, b => 2}.</input>
+false
+8> <input>#{a => 1, b => 2} == #{a => 1.0, b => 2.0}.</input>
 true
-7> <input>&lt;&lt;3:2>> &lt; &lt;&lt;128>>.</input>
+9> <input>&lt;&lt;2:2>> &lt; &lt;&lt;128>>.</input>
+true
+10> <input>&lt;&lt;3:2>> &lt; &lt;&lt;128>>.</input>
 false
 </pre>
+    <note>
+      <p>Prior to OTP 27, the term equivalence operators had a bug where they
+        considered <c>0.0</c> and <c>-0.0</c> to be the same term.</p>
+      <p>This was fixed in OTP 27 but legacy code may have expected them to
+        be considered the same. To help users catch errors that may arise from
+        an upgrade, the compiler raises a warning when <c>0.0</c> is
+        pattern-matched or used in a term equivalence test.</p>
+      <p>If you need to match <c>0.0</c> specifically, then the warning can be
+        silenced by writing <c>+0.0</c> instead, which produces the same term
+        but makes the compiler interpret the match as being done on
+        purpose.</p>
+    </note>
   </section>
 
   <section>
-- 
2.35.3

openSUSE Build Service is sponsored by