Exception 当传递非映射参数时,期望映射的函数何时以静默方式返回nil?

Exception 当传递非映射参数时,期望映射的函数何时以静默方式返回nil?,exception,map,clojure,Exception,Map,Clojure,我有点惊讶地看到,当您在需要映射的地方传递非映射的内容时,一些函数会无声地返回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

我有点惊讶地看到,当您在需要映射的地方传递非映射的内容时,一些函数会无声地返回
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}
user> (get {:a 1} :a)
1
很好,我递给他一张地图。让我们把一些不是映射的东西传递给doc说第一个参数应该是映射的函数:

user> (dissoc 1 :b)
ClassCastException java.lang.Long cannot be cast to clojure.lang.IPersistentMap  clojure.lang.RT.dissoc (RT.java:758)
user> (get 42 :a)
nil
公平地说,在运行时会抛出异常,问题也很清楚,这就是我所期望的行为

现在让我们看另一个函数:

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> (dissoc {:a 1 :b 2} :b)
{:a 1}
user> (get {:a 1} :a)
1
到目前为止还不错。让我们把一些不是映射的东西传递给doc说第一个参数应该是映射的函数:

user> (dissoc 1 :b)
ClassCastException java.lang.Long cannot be cast to clojure.lang.IPersistentMap  clojure.lang.RT.dissoc (RT.java:758)
user> (get 42 :a)
nil
也不例外。没什么。只是无声的“失败”

虽然两个函数的文档都明确指出第一个参数必须是映射,但当您传递的不是映射而不是另一个时,为什么一个函数会引发异常

在Clojure中,是否有一个“规则”来知道什么时候会出现异常或
nil
,或者我是否应该期望这种情况是不一致的


作为一个附带问题:如果get被修改为抛出一个异常,而不是在不传递应该传递的映射时默默地返回nil,那么Clojure和Clojure程序会“中断”吗?

get
用于处理所有关联数据结构。语言实现者可以选择检查参数是否是关联的,或者列出所有可以检查的关联内容的白名单,但是它在clojure.lang.RT中定义了一些特殊情况,并且还可以处理实现Map、IPersistentSet或ILookup的任何内容

现在,关于为什么它会在没有实现这些接口的情况下默默地返回nil,这是一个持续Clojure设计策略的实例,该策略默默地返回nil而不是失败。这个决定肯定有折衷之处,但这是Clojure做事情的普遍方式。

可能应该为非关联参数的
get
引发异常,如您的示例所示:

(contains? 42 :a)
;=> IllegalArgumentException 

(get 42 :a)
;=> nil ?? 

这是一个很好的例子。正如问题描述中所述,当前返回
nil
的行为很可能是一个bug,并且会掩盖编程错误。

(get[4 3 2 1]1)
=>3
(get{4 3 2 1}1)
=>1
(get“hello”1)
=>。它说的是“地图”,并不是说它需要地图
get
用于处理所有关联数据结构。@noisesmith:([map key][map key not found])在这两种情况下,第一个参数都称为“map”。还有,我知道42号是石头但是。。。整数42如何是关联数据结构?参数名为map,没有任何说明它必须是map。如果它是持久Clojure设计策略的实例,那么为什么dissoc示例不静默返回nil,而是抛出异常?我的问题是:是否有一个“规则”来知道何时会得到异常或何时会得到零?事情完全不一致吗?我不知道有什么规则。坦白地说,这是我最不喜欢的Clojure语言的一个方面(我确实喜欢Clojure,但就我而言,这是一个缺点)。我可以马上想到的Clojure函数返回
nil
关于“错误”类型参数的例子主要围绕查找(例如
get
和关键字查找)<另一方面,code>dissoc,返回一个新的映射;如果它返回一个数字或其他任意值,它将与它自己的签名不一致。你会考虑JavaLang.Stand是相联的吗?它不符合Culjress协议,但它是特殊的,我认为它是一个特例。异常应该在所有案例都被解释之后抛出,而不是返回null/nil。