2016-02-25 4 views
0

Может ли кто-нибудь объяснить следующее поведение функции + в Clojure (версия «1.8.0»)?Clojure `+` поведение с нулевыми значениями

(+ 1)  ;; 1 
(+ nil)  ;; nil 
(+ 5 nil) ;; java.lang.NullPointerException 
(+ nil nil) ;; java.lang.NullPointerException 
;; same behaviour with +' 

Примечание: это не сгенерирует исключение в ClojureScript:

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

ответ

3

взгляд на + истоком Clojure в:

(defn + 
    ([] 0) 
    ([x] (cast Number x)) 
    ([x y] (. clojure.lang.Numbers (add x y))) 
    ([x y & more] 
    (reduce1 + (+ x y) more))) 

так для арностью 1 он просто отбрасывает значение к номеру. Это действительно выглядит странно, что здесь нет никакой проверки для nil, я думаю, кто-то должен представить это как ошибку.

с другой стороны, вариант в clojurescript в:

(defn ^number + 
    ([] 0) 
    ([x] x) 
    ([x y] (cljs.core/+ x y)) 
    ([x y & more] 
    (reduce + (cljs.core/+ x y) more))) 

просто возвращает значение (которое также чувствует багги, так как (+ "hello") вернется "hello" (ну, не проверял, но все же))

для других арностей Clojure использует Numbers.add (что требует числа как Params, и бросает ошибку),

в то время как clojurescript использует этот макрос, насколько я знаю:

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

так что это просто добавление javascript, которое добавляет нули как нули.

+0

Я думаю, что вообще говоря, Clojure принимает отношение «мусор, мусор» к проверке аргументов, поэтому я думаю, что не слишком удивительно, что '+' не заботится о типе аргументов, которые ему даны. – glts

+0

'(+" hello ") ;; java.lang.ClassCastException: Невозможно использовать java.lang.String для java.lang.Number' – nha

+0

ну да. clojure не может преобразовать строку в Number. '(+ "Привет")' должен работать в clojurescript, не Clojure – leetwinski

Смежные вопросы