Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:24
erlang
6841-otp-Explain-the-term-equivalence-operators...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 6841-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 < atom < reference < fun < port < pid < tuple < 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 < atom < reference < fun < port < pid < tuple < 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><<2:2>> < <<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><<3:2>> < <<128>>.</input> +9> <input><<2:2>> < <<128>>.</input> +true +10> <input><<3:2>> < <<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
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor