Fork me on GitHub
#cljs-dev
<
2021-11-27
>
quoll17:11:55

(reposted since I sent this to the wrong channel) Working on the cljs.math thing, I’m encountering a couple of cases where `-0.0` is significant. The IEEE-754 standard represents `0.0` as `0x0000000000000000`, and `-0.0` as `0x8000000000000000`. In Clojure, I can use these easily:

user=> -0.0
-0.0
user=> (str -0.0)
"-0.0"
It works similarly in node, though conversion to a string does not:
> -0.0
-0
> "" + -0.0
'0'
> let z = -0.0
undefined
> z
-0
ClojureScript seems to lose this info entirely:
cljs.user=> -0.0
0
cljs.user=> (str -0.0)
"0"
Fortunately, the info is there:
cljs.user=> (def z -0.0)
#'cljs.user/z
cljs.user=> (let [buffer (js/ArrayBuffer. 8)
                  d (js/Float64Array. buffer)
                  b (js/Uint8Array. buffer)]
              (aset d 0 z)
              (str b))
"0,0,0,0,0,0,0,128"
(Obviously, I’m running on a little-endian machine 🙂) So the value of `z` does remember that the sign bit was set. It just doesn’t get printed. Is this something that there is interest in fixing? I’m happy to look at it, but not if no one cares 🙂

lilactown18:11:07

hm. it seems to be due to .toString

☝️ 1
lilactown18:11:41

> let n = -0
undefined
> n.toString()
'0'

lilactown18:11:10

(tested this in the browser but i'm guessing it's the same in node)

lilactown18:11:38

so toString drops the sign

lilactown18:11:22

it looks like showing the sign of zero in the JS REPL is a semi-recent update, since this article claims the same happens in Node.js: https://2ality.com/2012/03/signedzero.html

lilactown18:11:42

> let n = -0
undefined
> n.toLocaleString()
'-0'

lilactown18:11:32

probably dicey to change the way we stringify nums

quoll18:11:32

> hm. it seems to be due to `.toString` I agree, since the node repl (or my version of node anyway, which is v12.18.3) displays -0 for the value, but not when it’s converted to a string. I appreciate finding the difference for .toLocaleString! I wouldn’t have thought to look for that.

lilactown20:11:21

I don't think we could use .toLocaleString since it's not round trippable, and I think people use things like pr-str to print out valid EDN

☝️ 1
lilactown20:11:58

> let n = 10000
undefined
> n.toLocaleString()
'10,000'
> 10,000 // this will be parsed as the expression 10 <comma operator> 0
0