Clojure类型转换不会发生

时间:2018-01-02 22:09:40

标签: clojure floating coercion

我有以下函数给我一个哈希映射:

(build-quarter-note-group 60)
;;=> {0.0 "c'", 2.0 "cisis'", -2.0 "ceses'", 0.5 "cih'", -0.5 "ceh'", 1.0 "cis'", -1.0 "ces'", 1.5 "cisih'", -1.5 "ceseh'"}

然后我通过get在另一个函数中的地图中的键获得值。

(defn keynum->name
  ([keynum] (->> 0.0 (get (build-quarter-note-group keynum))))
  ([keynum transposition] (->> (float transposition) (get (build-quarter-note-group keynum)))))

由于密钥都是keynum->name函数中的浮点数,我确实尝试进行类型强制,但这种情况发生了:

(keynum->name 60 1) ;;=> nil
(get (build-quarter-note-group 60) (float 1)) ;;=> nil

(float 1)的结果会怎样?

1 个答案:

答案 0 :(得分:3)

引用the issue I opened in the Clojure Jira给出的答案:

我相信在最多8个键的地图中查找浮点数是一个意外的事实。

它因较大的映射和散列集而失败的原因是(double 1.0)和(float 1.0)的散列值不同。

user=> (hash (float 1.0))
1065353216
user=> (hash 1.0)
1072693248

示例中的所有值(如1.0和其他值)都默认为double类型。请注意,如果强制映射的键是浮动的,那么即使映射具有8个以上的键,查找也会成功:

user=> (get {(float 1.0) "a" 2.0 "b" 3.0 "c" 4.0 "d" 5.0 "e" 6.0 "f" 7.0 "g" 8.0 "h" 1 "i"} (float 1)) 
"a"

我的猜测是,除了通过小地图获得的事故恰好返回成功的查找外,此处的所有内容都按设计工作。

我相信使用小地图找到匹配的原因(浮点1)可能是因为小地图的实现是一个ArrayMap,其中查找键被顺序地与数组中的所有键进行比较clojure.core / =(或其Java等价物),并且:

user=> (= (float 1) (double 1))
true

因此,简而言之 - 地图中的键是双精度而不是浮点数。

(get (build-quarter-note-group 60) (double 1)) => "cis'"

相关问题