不,实际上您根本不想在代码中直接使用“使用”。Use 会修改调用它的整个命名空间,这可能会以难以预测的方式破坏您的代码。
相反,您应该做的是:实现一个日志接口(协议),编写一个“元构造函数”,将您在 config.clj 中设置的任何内容作为关键字调度。代码示例
(defprotocol ILog
(save-data [this msg] "Logs message in msg."))
(defn create-file-log
"Returns an object implementing ILog, opens and flushes java.io.File file."
[file]
(let [f ... ;; create file writer here
]
(reify ILog
(save-data [this msg] ;; Write code that writes data to file here
))))
;; create other implementations like database here or elsewhere
(defn create-log
"Creates a log of of the type passed in type-kw."
[type-kw]
(case type-kw
:file (create-file-log "./app-log.txt")
;; other types
))
现在,您只需使用配置文件中设置的任何关键字调用 create-log,并将返回的对象传递给需要进行日志记录的函数。显然,您也可以将其定义为全局对象,但我不建议这样做。
最终,您不仅想在配置中为所需的日志记录方法设置关键字(type-kw),还想在文件名或数据库 uri 等其他参数中传递类似的内容
{:log-method :file
:data {:fname "app-log.txt"}}
or
{:log-method :db
:data {:uri "....
...到您的 create-log 函数,该函数使用此结构来获取 reify 构造函数 create-file-log、create-db-log 等的参数。
编辑:
因为你不喜欢 switch 语句,这里是如何用多种方法做到这一点:
(defmulti create-log :logging-method)
(defmethod create-log :file
[arg-map]
(let [file (java.io.File. (:fname arg-map))]
(if (.exists file)
...
然后,您只需在 config.clj 中有一个条目
{...
:log {:logging-method :file
:fname "./log-file.txt"}}
要创建一个新的日志记录类型,您现在所要做的就是想象一个像上面那样的参数映射和一个用于 create-log 的构造函数方法。