TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Go 1.21 may have a clear(x) builtin

104 pointsby aviramhaover 2 years ago

17 comments

derrizover 2 years ago
Java has a specific hack for this which I discovered by accident a few years ago. Normally, given (primitive) double values d0 and d1, then boxing them does not affect equality testing - i.e. d0 == d1 if and only if Double.valueOf(d0).equals(Double.valueOf(d1)). However if d0 and d1 are both NaN, then the boxed versions ARE considered equal while d0 == d1 is false.<p>This inconsistency infuriated me when I discovered it but the Javadoc for Double.equals explicitly states that this anomaly is there to &quot;allow hash tables to work properly&quot;.
评论 #33674765 未加载
评论 #33675903 未加载
halpmehover 2 years ago
The issue with NaN equality is interesting, but is that really why they&#x27;re adding a clear(x) builtin? What if you want to remove a single-NaN key from a map? clear(x) seems like a band-aid at best if the Go team is strictly trying to fix removing NaN keys in maps.
评论 #33673840 未加载
martischover 2 years ago
&gt; This for loop is less efficient than clearing a map in one operation<p>For maps with keys that are reflexive with == the Go compiler already optimizes the range loop to a single efficient runtime map clear call: <a href="https:&#x2F;&#x2F;go-review.googlesource.com&#x2F;c&#x2F;go&#x2F;+&#x2F;110055" rel="nofollow">https:&#x2F;&#x2F;go-review.googlesource.com&#x2F;c&#x2F;go&#x2F;+&#x2F;110055</a>
评论 #33678280 未加载
inglorover 2 years ago
Interestingly JavaScript handles this correctly and specified Object.is equality that is different than `===` equality around NaNs so `const m = new Map(); m.set(NaN, 3); m.get(NaN)` returns 3 and `.delete` similarly works.
ch_123over 2 years ago
I&#x27;m curious why this is not implemented as a method on the map type (and others like list) instead of being a top-level builtin. I suppose it is consistent with other collection operations such as append and len... which I guess makes me wonder why those are builtins as well.
评论 #33674181 未加载
评论 #33674882 未加载
评论 #33674291 未加载
评论 #33675771 未加载
评论 #33674307 未加载
评论 #33679530 未加载
_old_dude_over 2 years ago
In Java, the primitive type double uses the IEEE-754 semantics and java.lang.Double uses the bits by bits comparison semantics [1] so List&lt;Double&gt;.remove() works correctly.<p>[1] <a href="https:&#x2F;&#x2F;docs.oracle.com&#x2F;en&#x2F;java&#x2F;javase&#x2F;19&#x2F;docs&#x2F;api&#x2F;java.base&#x2F;java&#x2F;lang&#x2F;Double.html" rel="nofollow">https:&#x2F;&#x2F;docs.oracle.com&#x2F;en&#x2F;java&#x2F;javase&#x2F;19&#x2F;docs&#x2F;api&#x2F;java.base...</a>
评论 #33674405 未加载
karmakazeover 2 years ago
Usage of NaN as hash key reminds me of the two uses of NULL in SQL. One is as unknown values which are never equal to anything even other NULL values. Another use is as a key for aggregate grouping. In that case the entry represents the aggregate for all the unknown values which aren&#x27;t equal but still grouped together. Different uses have different meanings so invalid in one use does not invalidate other uses.
akira2501over 2 years ago
You&#x27;ve already got zero and negative zero as an outlying case. I&#x27;m not sure why anyone would feel comfortable using floats as keys in a map. To anyone who has done this.. why? What was the use case?
评论 #33674300 未加载
评论 #33674533 未加载
评论 #33675938 未加载
zmjover 2 years ago
C# had the same NaN behavior until recently: <a href="https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;dotnet&#x2F;core&#x2F;compatibility&#x2F;core-libraries&#x2F;7.0&#x2F;equals-nan" rel="nofollow">https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;dotnet&#x2F;core&#x2F;compatibility&#x2F;...</a>
评论 #33675034 未加载
chubotover 2 years ago
Meh using floating point as keys for maps in any language is just asking for trouble -- it’s not just NaN<p>I don’t think there’s any real use case for it<p>I’d say clear() is good for clarity, and that’s it
评论 #33675428 未加载
kazinatorover 2 years ago
This looks like catching up to GNU Awk, which allows &quot;delete a&quot; to clear an associative array. That&#x27;s an extension over POSIX, which specifies &quot;delete a[key]&quot;.
kazinatorover 2 years ago
&gt; <i>This for loop is less efficient than clearing a map in one operation</i><p>That is not obvious; a compiler could have a pattern match for that exact AST pattern, and transform it to a delete operation. (Except for that pesky issue where two fail to be equivalent due to NaN keys.)<p>Quick and dirty, not entirely correct proof-of-concept in TXR Lisp:<p><pre><code> 1&gt; (macroexpand &#x27;(my-dohash (k v some.obj.hash) (print [some.obj.hash k]))) (dohash (k v some.obj.hash ()) (print [some.obj.hash k])) 2&gt; (macroexpand &#x27;(my-dohash (k v some.obj.hash) (del [some.obj.hash k]))) (clearhash hash) </code></pre> Impl:<p><pre><code> (defmacro my-dohash ((kvar vvar hash : result) . body) (if-match @(require ((del [@hash @kvar])) (null result)) body ^(clearhash hash) ^(dohash (,kvar ,vvar ,hash ,result) ,*body)))</code></pre>
评论 #33675878 未加载
yawaraminover 2 years ago
OK, now I understand why OCaml&#x27;s Float.compare function compares NaNs as equal to each other: <a href="https:&#x2F;&#x2F;discuss.ocaml.org&#x2F;t&#x2F;assertions-involving-nan&#x2F;10762&#x2F;4" rel="nofollow">https:&#x2F;&#x2F;discuss.ocaml.org&#x2F;t&#x2F;assertions-involving-nan&#x2F;10762&#x2F;4</a>
yencabulatorover 2 years ago
I&#x27;m more surprised they went with a new built-in instead of making the compiler recognize something like<p><pre><code> m = make(map[A]B, cap(m)) </code></pre> just like it already recognized<p><pre><code> for k := range m { delete(m, k) } </code></pre> and many other similar idioms.<p>(cap because len is not quite the same -- note, cap is not currently defined on maps)<p>EDIT: Likely because that&#x27;s an assigment on m, not a mutation of it, so it can&#x27;t be done e.g. in a function that gets m as argument.
unwindover 2 years ago
That was weird. Makes sense once you know about NaN&#x27;s incomparability, but still surprising.<p>I had to try it in Python (3.10.4, Windows on x86), it worked fine:<p><pre><code> &gt;&gt;&gt; import math &gt;&gt;&gt; a={math.nan: 1} &gt;&gt;&gt; a {nan: 1} &gt;&gt;&gt; del(a[math.nan]) &gt;&gt;&gt; a {}</code></pre>
评论 #33674722 未加载
评论 #33674763 未加载
评论 #33674789 未加载
kangaliooover 2 years ago
Would anything actually break if NaN == NaN equalled true?
评论 #33674827 未加载
评论 #33674332 未加载
评论 #33674490 未加载
评论 #33674535 未加载
anontrotover 2 years ago
Hold on a sec, the whole clearing map scenario. Is it for reusing within your fn or is it trying to free memory? If latter, I’ve just been hoping GC does its job