def和defonce在Clojure中有什么区别?
何时使用def,何时使用defonce?
def和defonce在Clojure中有什么区别?
何时使用def,何时使用defonce?
defonce
在变量已经定义时被跳过。
user> (def a 1) ;;=> #'user/a
user> a ;;=> 1
user> (def a 2) ;;=> #'user/a
user> a ;;=> 2
user> (defonce b 1) ;;=> #'user/b
user> b ;;=> 1
user> (defonce b 2) ;;=> nil
user> b ;;=> 1
如果名称没有根值,Defonce只会将名称绑定到根值。
例如,像Jay Fields blogs所述,当您想要重新加载命名空间但可能不需要全部重新加载时,可以与之配合使用。
(defonce ignored-namespaces (atom #{}))
(defn reload-all []
(doseq [n (remove (comp @ignored-namespaces ns-name) (all-ns))]
(require (ns-name n) :reload )))
关于何时使用defonce
,如果您正在使用带有热重载的系统(例如CLJS和mount以及re-frame),则defonce
有助于在重新加载之间保持状态。
类似情况是当您自己重新评估源文件(例如在REPL中)但想要保留绑定到符号的变量值时。