Clojure 以原子为单位增加一个值
我正在学习clojurescript,我偶然发现了这个片段Clojure 以原子为单位增加一个值,clojure,clojurescript,Clojure,Clojurescript,我正在学习clojurescript,我偶然发现了这个片段 :on-click (fn [] (swap! state/order update (:id gig) inc)) 我在文档中查找了update函数,它说update包含一个键和一个函数。将旧值从原子传递给函数,然后更新原子。如果atom中没有键的现有值,则将nil作为输入传递给函数。 当我在repl中尝试同样的方法时,它不起作用 (def atom-test (atom {})) (swap! atom-test update :
:on-click (fn [] (swap! state/order update (:id gig) inc))
我在文档中查找了update
函数,它说update包含一个键和一个函数。将旧值从原子传递给函数,然后更新原子。如果atom中没有键的现有值,则将nil作为输入传递给函数。
当我在repl中尝试同样的方法时,它不起作用
(def atom-test (atom {}))
(swap! atom-test update :aa inc)
NullPointerException clojure.lang.Numbers.ops (Numbers.java:1013)
添加fnil
以捕获此NullPointerException有效
user=> (swap! atom-test update :aa (fnil inc 0))
{:aa 1}
我无法理解为什么它在clojurescript的案例1中有效,为什么它在clojure repl的案例2中无效。谁能解释一下这里的诀窍是什么。对于cljs,操作通常安全地处理nil而不引起异常
cljs.user=> (update {} :a inc)
{:a 1}
cljs.user=> (inc nil)
1
cljs.user=> (+ 1 nil)
1
函数的
inc
需要满足number?
的参数。这在Clojure和ClojureScript中是正确的
如果您传递了其他内容,如nil
,则程序不正确:(inc nil)
具有未定义的行为。这样做不安全。它恰好返回1
,但这不能保证,这是一个意外的实现
例如,如果将文本字符串传递给inc
,ClojureScript将在编译时发出警告:
cljs.user=> (inc "a")
WARNING: cljs.core/+, all arguments must be numbers, got [string number] instead at line 1 <cljs repl>
cljs.user=>(包括“a”)
警告:cljs.core/+,所有参数都必须是数字,在第1行获得[string number]
也许在将来,编译器也会发出类似的警告,警告(inc nil)
,但更可能发生的是,编写的规范将涵盖核心函数,并指定cljs.core/inc
接受满足number?
的参数
TL;DR:在这里使用
fnil
是正确的做法。同样的原因,您可以在浏览器控制台中输入1+null
,以获得1
,而不会出现错误。我会在两边使用fnil
,我认为Clojure和ClojureScript的功能类似。