是否有任何制作本地'defonce'的方法? (Clojure)
假设我需要制作一个简单的计数器,并且每次调用此函数时都希望计数器增加,但这里有一件不愉快的事情:定义的“计数器”不是本地的,我可以轻松地将其值从另一个空间,打破封装。是否有任何制作本地'defonce'的方法? (Clojure)
(defn next []
(defonce counter (atom 0))
(println @counter)
(reset! counter (inc @counter)))
很多人说,如果我放置'私人'中继标记将是正确的。所以功能如下:
(defn next []
(defonce ^:private counter (atom 0))
(println @counter)
(reset! counter (inc @counter)))
但我仍然可以从另一空间访问'counter'。
有什么办法来实现这种封装,或者它只在协议级别?
这里是你应该怎么写你的next
功能:
(def ^{:arglists '([])} next
(let [counter (atom 0)]
#(let [after (swap! counter inc)
before (dec after)]
(println before)
after)))
这是一样的一个你的问题,但它是线程安全的,完全封装counter
原子。
完美!但是......'^ {:arglists'([])}' - 这是为了什么? – errfrom
@errfrom这不是真的有必要;尝试'(clojure.repl/doc下一个)'有和没有它,你可以决定是否要包括它。 –
私人的作品好,你不应该有其他的命名空间访问
user> (ns a)
nil
a> (defonce ^:private counter (atom 0))
#'a/counter
a> (defn next []
(println @counter)
(swap! counter inc))
#'a/next
a> (next)
0
1
a> (next)
1
2
a> (next)
2
3
a> (next)
3
4
a> (ns b)
nil
b> (require 'a)
nil
b> (a/next)
4
5
b> (a/next)
5
6
b> a/counter
CompilerException java.lang.IllegalStateException: var: a/counter is not public
b> (ns a)
nil
a> a/counter
#object[clojure.lang.Atom 0x1ec64eb6 {:status :ready, :val 6}]
也有一些小问题:
- 在纳秒的顶层定义
counter
,而不是里面的功能,无论是具有相同的效果,但*更清晰 - 更改
reset!
至(swap! counter inc)
,它将是线程安全的
您确定您可以访问另一个ns的私有原子吗? – mishadoff
@mishadoff [是。](https://github.com/bbatsov/clojure-style-guide/blob/cb0be3a21c234fbb5bd152e3d67ffbf104140077/README.md#access-private-var) –