Skip to content

Instantly share code, notes, and snippets.

@mfikes
Last active May 22, 2021
Embed
What would you like to do?
Playing with BigInt in ClojureScript

Usage

Fire up a REPL using any of the following forms.

Node

clj -Srepro -Sdeps '{:deps {org.clojure/clojurescript {:git/url "https://github.com/mfikes/clojurescript" :sha "ed1e7373a9ecd8b52084dc438e6c21d23dba47ca"}}}' -m cljs.main -re node

Graal.JS

clj -Srepro -Sdeps '{:deps {org.clojure/clojurescript {:git/url "https://github.com/mfikes/clojurescript" :sha "ed1e7373a9ecd8b52084dc438e6c21d23dba47ca"}}}' -m cljs.main -re graaljs

Chrome Browser

clj -Srepro -Sdeps '{:deps {org.clojure/clojurescript {:git/url "https://github.com/mfikes/clojurescript" :sha "ed1e7373a9ecd8b52084dc438e6c21d23dba47ca"}}}' -m cljs.main -ro '{:launch-browser false}' -r

and point Chrome at http://localhost:9000 (Use Chrome 67 or later.)

Try Things

Then try some things with arbitrary-precision integers.

cljs.user=> (+ 9007199254740991 2)        ; (+ (.-MAX_SAFE_INTEGER js/Number) 2)
9007199254740992
cljs.user=> (+ 9007199254740991N 2N)
9007199254740993N

Comparing and sorting

cljs.user=> (< 1N 2)
true
cljs.user=> (sort [4N 6N -12N 10 4 0 0N])
(-12N 0 0N 4N 4 6N 10)
cljs.user=> (max 1N 7N 3)
7N

quot, mod and friends

cljs.user=> (quot 17N 3N)
5N
cljs.user=> (rem 17N 3N)
2N
cljs.user=> (mod 17N 3N)
2N
cljs.user=> (js-mod 17N 3N)
2N

bitwise operators

cljs.user=> (bit-shift-right 10N 1N)
5N
cljs.user=> (bit-or 3N 4N)
7N

You can't mix fixed-precision and arbitrary-precision integers like you can in Clojure:

cljs.user=> (+ 1 2N)
TypeError: Cannot mix BigInt and other types, use explicit conversions

but this works

cljs.user=> (+ (bigint 1) 2N)
3N

How Does This Work?

In this branch, ClojureScript has a few simple revisions:

  1. If the Clojure reader produces a clojure.lang.BigInt, ClojureScript is revised to emit that number with an n suffix, which means it is interpreted as a JavaScript BigInt.
  2. When printing JavaScript BigInt values it prints the number with an N suffix.
  3. An implementation of cljs.core/bigint is added, supporting coercion
  4. Support for BigInt in cljs.core/compare when comparing with JavaScript numbers.
  5. Add support for BigInt in interal fix implementation

More Info

@lgrapenthin
Copy link

lgrapenthin commented May 22, 2021

Great! Any chance for this to be merged upstream?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment