Clojure`+;`具有零值的行为

Clojure`+;`具有零值的行为,clojure,nullpointerexception,clojurescript,Clojure,Nullpointerexception,Clojurescript,有人能解释一下Clojure(版本“1.8.0”)中函数的以下行为吗 注意:它不会在ClojureScript中引发异常: (+ 1) ;; 1 (+ nil) ;; nil (+ 5 nil) ;; 5 (+ nil nil) ;; 0 请看clojure的+源代码: (defn + ([] 0) ([x] (cast Number x)) ([x y] (. clojure.lang.Numbers (add x y))) ([x y & m

有人能解释一下Clojure(版本“1.8.0”)中函数的以下行为吗

注意:它不会在ClojureScript中引发异常:

(+ 1)       ;; 1
(+ nil)     ;; nil
(+ 5 nil)   ;; 5
(+ nil nil) ;; 0

请看clojure的
+
源代码:

(defn +
  ([] 0)
  ([x] (cast Number x))
  ([x y] (. clojure.lang.Numbers (add x y)))
  ([x y & more]
     (reduce1 + (+ x y) more)))
所以对于算术1,它只是将一个值转换为一个数字。这看起来真的很奇怪,这里没有检查
nil
,我想应该有人将此作为bug提交

另一方面,clojurescript的变体:

(defn ^number +
  ([] 0)
  ([x] x)
  ([x y] (cljs.core/+ x y))
  ([x y & more]
    (reduce + (cljs.core/+ x y) more)))
只返回值(这也感觉有问题,因为
(+“hello”)
将返回
“hello”
(虽然还没有测试过,但仍然如此))

对于其他算术,clojure使用
数字。添加
(需要数字作为参数,并抛出错误)

据我所知,clojurescript使用这个宏:

(core/defmacro ^::ana/numeric +
  ([] 0)
  ([x] x)
  ([x y] (core/list 'js* "(~{} + ~{})" x y))
  ([x y & more] `(+ (+ ~x ~y) ~@more)))

因此,这只是添加了javascript,将空值添加为零。

查看clojure的
+
源代码:

(defn +
  ([] 0)
  ([x] (cast Number x))
  ([x y] (. clojure.lang.Numbers (add x y)))
  ([x y & more]
     (reduce1 + (+ x y) more)))
所以对于算术1,它只是将一个值转换为一个数字。这看起来真的很奇怪,这里没有检查
nil
,我想应该有人将此作为bug提交

另一方面,clojurescript的变体:

(defn ^number +
  ([] 0)
  ([x] x)
  ([x y] (cljs.core/+ x y))
  ([x y & more]
    (reduce + (cljs.core/+ x y) more)))
只返回值(这也感觉有问题,因为
(+“hello”)
将返回
“hello”
(虽然还没有测试过,但仍然如此))

对于其他算术,clojure使用
数字。添加
(需要数字作为参数,并抛出错误)

据我所知,clojurescript使用这个宏:

(core/defmacro ^::ana/numeric +
  ([] 0)
  ([x] x)
  ([x y] (core/list 'js* "(~{} + ~{})" x y))
  ([x y & more] `(+ (+ ~x ~y) ~@more)))

所以这只是javascript的添加,它将空值添加为零。

我认为一般来说,Clojure对参数验证采取“垃圾输入,垃圾输出”的态度,所以我认为,
+
不关心它给出的参数的类型也就不足为奇了。
(+“hello”);;java.lang.ClassCastException:无法将java.lang.String转换为java.lang.Number
嗯,是的。clojure无法将字符串转换为数字
(+“hello”)
应该在clojurescript中工作,而不是clojure
cljs.user=>(+“hello”)“hello”cljs.user=>(+nil”“)“null”cljs.user=>(+nil 123)123 cljs.user=>(+“123”nil)“123null”
@glts,是的,但既然它为算术2+抛出了一个错误,那么为算术1抛出它不合乎逻辑吗?想象一下:
(apply+items)
其中
items
是某个复杂函数调用的结果。因此,当items=[nil]时,它将返回
nil
,但如果items=[nil,1,2,nil],它显然会抛出一个错误。当你稍后在某处使用结果时,我打赌你更愿意看到异常,而不是为了这个奇怪的
nil
检查你的所有代码,然后在这个真正意想不到的地方找到它(我个人并不期望
nil
作为一个加法结果),我认为一般来说Clojure采用了“垃圾输入”,“垃圾处理”对参数验证的态度,所以我认为,
+
不关心它给出的参数的类型也就不足为奇了;;java.lang.ClassCastException:无法将java.lang.String转换为java.lang.Number
嗯,是的。clojure无法将字符串转换为数字
(+“hello”)
应该在clojurescript中工作,而不是clojure
cljs.user=>(+“hello”)“hello”cljs.user=>(+nil”“)“null”cljs.user=>(+nil 123)123 cljs.user=>(+“123”nil)“123null”
@glts,是的,但既然它为算术2+抛出了一个错误,那么为算术1抛出它不合乎逻辑吗?想象一下:
(apply+items)
其中
items
是某个复杂函数调用的结果。因此,当items=[nil]时,它将返回
nil
,但如果items=[nil,1,2,nil],它显然会抛出一个错误。当您稍后在某个地方使用结果时,我打赌您更希望看到异常,而不是查看所有代码以查找这个奇怪的
nil
,从而在这个真正出乎意料的地方找到它(我个人并不期望
nil
作为一个附加结果)