不会发生Clojure类型转换

问题描述 投票:1回答:1

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

(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'"}

然后我通过geting另一个函数中的地图中的键来获取值。

(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)的结果会怎样?

clojure floating coercion
1个回答
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'"

© www.soinside.com 2019 - 2024. All rights reserved.