ClojureScript плавает хэши в виде целых

Сначала я думал, что это ошибка, но, глядя на исходный код, это явно преднамеренно. Кто-нибудь знает, почему это делается? Это несовместимо с Clojure и тонким источником ошибок.

(hash 1)   ; => 1
(hash 1.5) ; => 1

https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/core.cljs#L985

(defn hash
  "Returns the hash code of its argument. Note this is the hash code
   consistent with =."
  [o]
  (cond
    (implements? IHash o)
    (bit-xor (-hash ^not-native o) 0)

    (number? o)
    (if (js/isFinite o)
      (js-mod (Math/floor o) 2147483647)
      (case o
        Infinity
        2146435072
        -Infinity
        -1048576
        2146959360))
  ...))

1 ответ

Решение

JavaScript имеет только один тип чисел: 64-разрядное число с плавающей запятой между -(2^53)-1 и (2 ^ 53) -1. Однако побитовые операции работают с 32-битными знаковыми целыми числами. Таким образом, преобразование с потерями необходимо, когда число с плавающей запятой преобразуется в хеш, который работает с побитовыми операторами. Волшебный номер 2147483647 для операции по модулю в core.cljs/hash максимальное целое число, представляемое через 32-битное число со знаком. Обратите внимание, что есть также специальная обработка для значений Infinity а также -Infinity,

Другие вопросы по тегам