stu*_*ing 10 clojure read-eval-print-loop
我正在尝试使用随机函数确定的键创建地图文字:
user=> {(str (rand-int 5)) "hello" (str (rand-int 5)) "goodbye"}
IllegalArgumentException Duplicate key: (str (rand-int 5)) clojure.lang.PersistentArrayMap.createWithCheck (PersistentArrayMap.java:71)
Run Code Online (Sandbox Code Playgroud)
而
user=> {(str (rand-int 5)) "hello" (str (rand-int 6)) "goodbye"}
{"4" "hello", "2" "goodbye"}
Run Code Online (Sandbox Code Playgroud)
Reader似乎将密钥视为未评估列表.
我在文档中找不到任何有关此内容的详细信息.有没有人可以帮我理解这一点?
走过Clojure编译器的源代码,我发现了以下内容:
这个类LispReader包含嵌套类MapReader,负责读取地图文字.它的方法invoke是在符号之间读取Clojure形式{,}并通过调用方法返回一个地图(Clojure形式). RT.map
RT.map 调用 PersistentHashMap.createWithCheck其中的重复键实际检查执行.由于我们正在构建Clojure表单的映射,因此即使有两个相同的表单评估为不同的值(例如在您的示例中),也会触发检查.
所有Clojure表单的评估都是在Compiler类中进行的,特别是在它的嵌套类中计算地图表单MapExpr.它的方法eval评估map的键和值,并再次使用构建持久映射RT.map.因此,检查是否将对评估值执行重复键,这就是为什么以下代码也将失败:
(let [x :foo y :foo]
{x :bar y :baz}) ;; throws duplicated key exception
Run Code Online (Sandbox Code Playgroud)
我不确定为什么作者决定在表格地图和价值图上检查重复的密钥.可能,它是某种"失败快速策略":这种实现将在编译阶段早期报告错误(尽管可能存在误报),并且此检查不会被延迟到运行时.