是否有任何制作本地'defonce'的方法? (Clojure的)

时间:2017-07-07 11:05:43

标签: clojure counter local private encapsulation

假设我需要创建一个简单的计数器,并且我希望每次调用此函数时计数器都会递增,但这是一个令人不愉快的事情:定义的'计数器'不是本地的,我可以轻松地从另一个空间更改其值,这破坏了封装。

(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)))

但我仍然可以从另一个空间进入“柜台” 有没有办法实现这种封装,或者只是在协议级别?

2 个答案:

答案 0 :(得分:4)

以下是编写 needSubIdCheck = $("#needSubIdCheck").text(); liveSupplierCount = $("#liveSupplierCount").text(); subIdCount = $("#subIdCount").text(); if(needSubIdCheck == 'true') { if( liveSupplierCount > subIdCount ) { alert("subIDS Needs to be assigned"); return false; } } 函数的方法:

next

这与你问题中的那个相同,只是它是线程安全的并且完全封装了(def ^{:arglists '([])} next (let [counter (atom 0)] #(let [after (swap! counter inc) before (dec after)] (println before) after))) 原子。

答案 1 :(得分:1)

私有效果很好,您不应该从其他名称空间访问

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}]

还有一些小问题:

  1. 在ns的顶层定义counter,而不是在函数内部,两者都有相同的效果,但顶级更清晰
  2. reset!更改为(swap! counter inc),它将是线程安全的