扩展交换!Clojure中nil型的行为
假设我有var原子var扩展交换!Clojure中nil型的行为,clojure,Clojure,假设我有var原子var (def atom-val (atom [])) 还假设原子的标准行为: (swap! atom-val conj {:b "2"}) => #object[clojure.lang.Atom 0x6500d3fd {:status :ready, :val [{:a "2"}] (@atom-val) => #object[clojure.lang.Atom 0x6500d3fd {:status :ready, :val [{:a "2"}] 我希望
(def atom-val (atom []))
还假设原子的标准行为:
(swap! atom-val conj {:b "2"})
=> #object[clojure.lang.Atom 0x6500d3fd {:status :ready, :val [{:a "2"}]
(@atom-val)
=> #object[clojure.lang.Atom 0x6500d3fd {:status :ready, :val [{:a "2"}]
我希望创建与使用nil对象相同的行为,但不执行操作:
(def atom-val nil)
(swap! atom-val conj "New val")
当然,我会得到一个NullPointerException。但我希望什么都没发生,就这样吧。我不需要每次都写尝试,我只需要描述的行为
我明白了!是函数,atom是函数,atom返回clojure.lang.IAtom,clojure.lang.IAtom是接口。我无法扩展接口。
如何获得所描述的行为
我有一个全局动态变量,它等于零
(def ^:dynamic atom-val nil).
每当使用compojure创建线程的环处理程序时,我都将atom val绑定到
(defn func [handler]
(fn [request]
(binding [atom-val (atom [])]
(handler request)
)
)
因此,我在不同的功能中有这样一种形式:
(swap! atom-val conj "New val").
我可以在不同功能的内部/外部到处运行它很多次。每次检查atom val是否为null都非常糟糕。函数必须进行交换!,但有时,当函数进行交换时,atom val无法正确初始化!外环处理器,在绑定之前
所以我决定这样做:我想扩展交换!原子的协议,当传递原子值为nil时,它不能抛出NullPointerException。您需要使用fnil。看
例如:
(def atom-val nil)
(def nil-swap! (fnil swap! (atom [])))
(nil-swap! atom-val conj "New val") => ["New val"]
别忘了随时打开浏览器选项卡 所以,你想交换!零分?我不知道你的行动和无所事事是什么意思
至少对我来说,交换是毫无意义的!零值;如果它对你有影响,你应该回顾一下原子到底是什么。也许你的意思是,当给定nil而不是atom引用时,交换就发生了!我什么也不做
如果是这样的话,您只需使用自己的函数为您执行该检查:
(defn nilable-swap!
[a f]
(when a (swap! a f)))
但我真的不建议你这样做,如果这是你想做的,这是一个坏的设计和控制流的迹象。当然,如果你不确定的话,检查原子引用是否为零是有意义的,但是你真的需要例行检查吗?你真的不知道你得到了原子引用吗
我想我可能已经回答了你的问题,但如果我误解了,请随时澄清,我会更新/删除答案。如果你想要一个什么都不做的原子,你可以写:
(def noop-atom
(reify clojure.lang.IAtom
(reset [_ _])
(swap [_ _])
(swap [_ _ _])
(swap [_ _ _ _])
(swap [_ _ _ _ _])
(compareAndSet [_ _ _])))
然后,您可以使用这个原子作为动态变量的根值
如果您的目标是在响铃请求/响应的生命周期内管理状态,您可以编写一个自定义。可以询问此替换的目的吗?谢谢,您已经给出了正确的答案。然后我找到了deref协议。