What's the easiest way to parse numbers in clojure?

后端 未结 10 1558
长发绾君心
长发绾君心 2020-12-08 09:30

I\'ve been using java to parse numbers, e.g.

(. Integer parseInt  numberString)

Is there a more clojuriffic way that would handle both int

10条回答
  •  庸人自扰
    2020-12-08 10:11

    Not sure if this is "the easiest way", but I thought it was kind of fun, so... With a reflection hack, you can access just the number-reading part of Clojure's Reader:

    (let [m (.getDeclaredMethod clojure.lang.LispReader
                                "matchNumber"
                                (into-array [String]))]
      (.setAccessible m true)
      (defn parse-number [s]
        (.invoke m clojure.lang.LispReader (into-array [s]))))
    

    Then use like so:

    user> (parse-number "123")
    123
    user> (parse-number "123.5")
    123.5
    user> (parse-number "123/2")
    123/2
    user> (class (parse-number "123"))
    java.lang.Integer
    user> (class (parse-number "123.5"))
    java.lang.Double
    user> (class (parse-number "123/2"))
    clojure.lang.Ratio
    user> (class (parse-number "123123451451245"))
    java.lang.Long
    user> (class (parse-number "123123451451245123514236146"))
    java.math.BigInteger
    user> (parse-number "0x12312345145124")
    5120577133367588
    user> (parse-number "12312345142as36146") ; note the "as" in the middle
    nil
    

    Notice how this does not throw the usual NumberFormatException if something goes wrong; you could add a check for nil and throw it yourself if you want.

    As for performance, let's have an unscientific microbenchmark (both functions have been "warmed up"; initial runs were slower as usual):

    user> (time (dotimes [_ 10000] (parse-number "1234123512435")))
    "Elapsed time: 564.58196 msecs"
    nil
    user> (time (dotimes [_ 10000] (read-string "1234123512435")))
    "Elapsed time: 561.425967 msecs"
    nil
    

    The obvious disclaimer: clojure.lang.LispReader.matchNumber is a private static method of clojure.lang.LispReader and may be changed or removed at any time.

提交回复
热议问题