var或ref / atom / agent用于常量值?

时间:2013-11-15 05:57:54

标签: clojure var agent ref

我想谦虚地问......

什么,“var或ref / atom / agent for constant values?”,请问? 当然,我确实使用vars作为常量值。

但是我总是想知道当值像常量一样时我应该使用哪一个但它们应该在运行时分配,而不是在编译时分配(当读取代码时)。

例如,想一下用户配置文件中编写的一些java属性。 它们应该在运行时分配,因为数据不在代码中。 但是它们也应该在读取数据之前定义,因为其他代码引用它们。

在这种情况下,

何时使用'var's?:

  • 我定义'var',或者只是声明'var'(当没关系的时候)。
  • 然后我通过读取选项文件的函数重新定义了那些'var'。
  • 但覆盖'var'感觉很糟糕,或者定义'var'内部函数感觉很奇怪。

何时使用ref / atom / agent?:

  • 我将ref / atom / agents分配给'var's。
  • 然后我通过读取选项文件的函数更新那些ref / atom / agents。
  • 但由于整个计划都使用了这些值,所以我担心它们的成本。
  • ...使用太多的@宏有点烦人。

我不知道应该用什么。

在这些情况下你会用什么?

“变种的? “REF /原子/代理的?甚至'延迟'?

提前致谢。

1 个答案:

答案 0 :(得分:2)

如果您正在考虑所有或一组“常数”,可以在一个时间点学习,让我们称之为“属性”。

让我们制作一个“吸吮他们”的配置:

(defn resource [path]
  (when path
    (-> (Thread/currentThread) .getContextClassLoader (.getResource path))))

(def props
  (edn/read-string 
    (slurp (io/file (resource (System/getProperty "your.conf"))))))

(defn conf [& path]                  ;; e.g. (conf :db :uri)
  (get-in props (vec path)))

您的属性(例如“常量”)文件“your.conf”将包含在以下行中:

{:db
    {:uri "datomic:mem://dbname"
     :other-property 42}

 :rabbit
        {:host "192.168.1.17"
         :port 5672
         :exchange "xyz-exchange"
         :queue "zq"
         :exchange.type "direct"
         :vhost "/some-broker"
         :username "user"
         :password "strong"}}

然后在您的程序/其他命名空间中,您可以访问所有这些属性:

(conf :db :uri)               ;; will "constant"ly return "datomic:mem://dbname"
(conf :rabbit :host)          ;; will "constant"ly return "192.168.1.17"
(conf :db :other-property)    ;; will "constant"ly return 42

在“现实生活中”,上面的“道具”var可能会检查“-D”路径,具有默认值并处理异常,但它有点简化以说明这一点。