增加一个原子的值

Increment a value in of an atom

我正在学习 clojurescript,我看到了这段代码。

:on-click (fn [] (swap! state/order update (:id gig) inc))

我查找了 update 函数的文档,它说更新需要一个键和一个函数。将旧值从原子传递给函数,然后更新原子。如果原子中的键没有现有值,则将 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}

我不明白为什么它在 case 1 中的 clojurescript 中有效,为什么在 case 2 中的 clojure repl 中无效。任何人都可以解释这里的技巧。

对于 cljs,操作安全地处理 nil 而不会导致异常是很常见的。

cljs.user=> (update {} :a inc)
{:a 1}
cljs.user=> (inc nil)
1
cljs.user=> (+ 1 nil)
1

https://cljs.github.io/api/syntax/nil

inc 函数需要一个满足 number? 的参数。在 Clojure 和 ClojureScript 中也是如此。

如果您传递其他内容,例如 nil,则程序不正确:(inc nil) 具有未定义的行为。这样做是不安全的。它恰好发生在 return 1 但这并不能保证并且是实施的意外。

例如,如果您改为将文字字符串传递给 inc,ClojureScript 将在编译时发出警告:

cljs.user=> (inc "a")
WARNING: cljs.core/+, all arguments must be numbers, got [string number] instead at line 1 <cljs repl>

也许在未来,编译器可以类似地为 (inc nil) 发出警告,但更有可能发生的是编写涵盖核心功能的规范,其中 cljs.core/inc 被指定为接受满足 number?.

的参数

TL;DR:在这里使用 fnil 是正确的做法。