我有这个函数:
(defn get-validator []
(UrlValidator. (into-array ["https"])))
我希望它只在第一次调用时求值一次,然后只返回结果。哪一种写法更好:
(def get-validator (UrlValidator. (into-array ["https"])))
(def ^:const get-validator (UrlValidator. (into-array ["https"])))
(defonce get-validator (UrlValidator. (into-array ["https"])))
还是有其他更好的方法?文档显示defonce
是正确的,但没有明确说明。
首先,def
使用给定的名称和可选的鉴于"init"值,当加载/编译命名空间时(请注意,加载之间基本上没有太大的区别编译,这就是为什么你不想有def
的副作用)
三个版本大致相同,区别如下:
:^const
允许内联此值;这影响了以下内容类中的性能改进代码defonce
防止在命名空间结束后重新定义var重载;这是最有用的,如果你def
可变状态,那你
在任何情况下,第一次需要ns,将执行代码然后它基本上就被单独留下了(想象一下静态变量)属性)。
所有的说:如果UrlValidator
有内部状态,你可能仍然是当你需要的时候,最好使用一个函数来创建一个新的。
另一种方法,假设UrlValidator.
是引用透明的,是使用clojure.core/memoize
。
(defn get-validator []
(UrlValidator. (into-array ["https"])))
(def uval (memoize get-validator))
然后在需要验证器时使用(uval)
。由于记忆,get-validator
将只被调用一次。
这种方法只会在第一次执行(uval)
时调用一次UrlValidator.
。所有其他的建议将调用UrlValidator.
,一次,当命名空间被加载。