当您传递的内容不是预期地图的地图时,我会看到某些函数以某种方式静默返回nil
(或您传递的默认值),这有点让我感到惊讶。
首先采用以下文档和示例,它按预期工作:
user> (doc dissoc)
-------------------------
clojure.core/dissoc
([map] [map key] [map key & ks])
dissoc[iate]. Returns a new map of the same (hashed/sorted) type,
that does not contain a mapping for key(s).
dissoc
的第一个参数必须是根据文档的地图,所以这里会发生什么:
user> (dissoc {:a 1 :b 2} :b)
{:a 1}
工作正常,我通过了地图。让我们传递一些不是映射到该函数的函数,该函数的doc说第一个参数应该是map:
user> (dissoc 1 :b)
ClassCastException java.lang.Long cannot be cast to clojure.lang.IPersistentMap clojure.lang.RT.dissoc (RT.java:758)
足够公平,在运行时抛出异常并且问题很明显,这是我预期的行为。
现在让我们采取另一种功能:
user> (doc get)
-------------------------
clojure.core/get
([map key] [map key not-found])
Returns the value mapped to key, not-found or nil if key not present.
get
的第一个参数必须是按照文档的地图,这里会发生什么:
user> (get {:a 1} :a)
1
到目前为止一切顺利。让我们传递一些不是映射到该函数的函数,该函数的doc说第一个参数应该是map:
user> (get 42 :a)
nil
没有例外。没什么。只是沉默"失败"。
当你传递的东西不是地图而不是另一个时,一个函数如何抛出异常,尽管这两个函数都是' docs清楚地说明第一个参数必须是地图?
是否有"规则"知道什么时候,在Clojure中,你会得到例外或nil
或者我是否应该期望这种东西不一致?
作为一个侧面问题:Clojure和Clojure计划会打破"打破"如果,例如, get 被修改为抛出异常,而不是在你没有通过你应该去的地图时默默地返回nil?
答案 0 :(得分:3)
对于非关联参数的get
,可能会抛出 ,例如:
(contains? 42 :a)
;=> IllegalArgumentException
(get 42 :a)
;=> nil ??
这是open issue in Clojure's Issue Tracker。正如问题描述中所述,返回nil
的当前行为很可能是一个错误,并且可能会掩盖编程错误。
答案 1 :(得分:1)
get
旨在处理所有关联数据结构。语言实现者可以选择检查参数是否是关联的,或者创建一个可以检查的所有关联事物的白名单,但是它有一些在clojure.lang.RT中定义的特殊情况,并且也可以在任何实现Map或IPersistentSet或ILookup的东西。
the code is not too hard to grok
现在,至于为什么它会默默地在没有实现这些接口的东西上返回nil,这是一个持久的Clojure设计策略的实例,它默默地返回nil而不是失败。这个决定肯定有权衡,但这是Clojure做事的普遍方式。