cljs-dev

dnolen 2023-09-26T01:45:51.424689Z

Experimenting w/ BigInt support - https://github.com/clojure/clojurescript/pull/214

dnolen 2023-09-26T01:46:38.596529Z

fairly low impact, as there's no direct reference to BigInt anywhere and you have to configure Closure to handle it

dnolen 2023-09-26T01:47:18.426669Z

but if you set it up - it's pretty cool, 1N or Long constant values bigger than JS max safe integer values - are emitted as BigInt

dnolen 2023-09-26T01:47:39.769329Z

I did a quick pass to make sure that equiv / hashing works as expected

dnolen 2023-09-26T01:49:12.715839Z

I pondered the Clojure numeric tower a bit - but after writing pages and pages of notes - I'm not so convinced about creating confusion about numerical interop

dnolen 2023-09-26T01:50:05.463019Z

in the end JavaScript only really has Number (Double) and BigInt - trying to pretend otherwise just seems more like more trouble at the moment

dnolen 2023-09-26T01:51:40.919559Z

still need to fix tools.reader but I think this is probably an easy one

dnolen 2023-09-26T01:54:26.593699Z

re: numeric tower, my primary thought is that Ratio really exists because of Java loss of precision when dividing primitive integral types - however JS choice to use Double was more or less a simplification to avoid that particular footgun from the start

hifumi123 2023-09-26T02:21:51.295989Z

hmm i dont understand the latter bit, doesnt JS also have loss of precision in that case? The way I understand Clojure’s Ratio is that it defaults to BigInt to simplify the types involved with rationals. e.g. in Common Lisp, the numerator and denominator of a rational is the integer type, which includes everything from bits to bignums, so forms like (+ 1/2 1/2) will evaluate to a value of type bit. I assume the choice of BigInt in Clojure is to have this sort of flexibility (though there is no way to statically determine if a part in a Clojure ratio may be represented with a fixnum, i.e. the most we can assume out of (+ 1/2 1/2) in clojure is that we have a BigInt )

dnolen 2023-09-26T02:24:58.912809Z

this is true, but defaulting to Double in JS prevents basic nasty stuff like 1/2 and then doing some say iteration bounding on that result

dnolen 2023-09-26T02:25:53.620089Z

the big problem for numeric tower is that in JS you cannot generically combine BigInt and Number

dnolen 2023-09-26T02:26:34.342149Z

Clojure's numeric tower could be summarized Long -> BigInt -> Ratio -> Double -> BigDecimal I think.

dnolen 2023-09-26T02:26:54.361059Z

but this sequence makes things kind of difficult in JS

dnolen 2023-09-26T02:27:07.188409Z

first off there is no integral type in JS (except BigInt) nor anyway to figure it out

dnolen 2023-09-26T02:29:19.870309Z

the other thing which is practical is that the numeric tower in Clojure involves a lot of code and everything references everything

dnolen 2023-09-26T02:29:26.489989Z

which is a dead code elimination hole

hifumi123 2023-09-26T02:29:29.390779Z

re: bigint: ah right, numbers are technically all doubles, and integers go up to whatever the length of a double’s mantissa is… so we cant just promote Number to BigInt when mixing them like in Java, or else we could be taking in a number with a fractional part and lose it

dnolen 2023-09-26T02:30:50.382479Z

I would say it's even worse that, JS is not really doubles and integers, only doubles

hifumi123 2023-09-26T02:30:50.610649Z

in that case i think youre right that cljs should just stick with the js limitations and not try to brush it over

dnolen 2023-09-26T02:31:05.395259Z

but semantically you can clamp JS to 32bit ints

dnolen 2023-09-26T02:31:22.687359Z

but again you cannot figure this out really - no tagging

dnolen 2023-09-26T02:32:15.124579Z

can't just wrap everything to gain tagging w/o creating an interop nightmare

dnolen 2023-09-26T02:33:58.920779Z

one escape hatch is Symbol @@toPrimitive - but still, can't combine w/ JS math libs then

dnolen 2023-09-26T23:11:15.015099Z

experimenting with a wrapper type that uses @@toPrimitive

dnolen 2023-09-26T23:11:16.104119Z

https://github.com/clojure/clojurescript/pull/214

dnolen 2023-09-26T23:12:48.409619Z

this makes using 1N values not fail when calling into the core apis - i.e (range 5N) etc.