我有这个功能正确加载我的命名空间:
(defn load-module [module-name]
(use module-name)
)
我的“等效”宏不起作用:
(defmacro load-module-macro [module-name]
`(
(use '~module-name)
)
)
我不明白这个问题。
此外,我想使用此宏来加载模块在配置中选择。在我的config.clj中,我用我的记录器模块的命名空间定义了一个包含“save-data”函数的var。然后我想在我的核心程序中加载指定的记录器。所以我可以选择直接在我的配置文件中使用记录器(磁盘上的记录器,数据库中的记录器......)。这是最好的方法吗?
编辑:
错误消息
IllegalArgumentException Don't know how to create ISeq from: java.lang.Character clojure.lang.RT.seqFrom (RT.java:505)
答案 0 :(得分:3)
不,实际上你并不想使用"使用"直接在代码中。使用会修改调用它的整个命名空间,这可能会以难以预测的方式破坏您的代码。
相反,你应该做的是: 实现日志记录接口(Protocol),编写"元构造函数"将您在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的构造函数方法。
答案 1 :(得分:1)
我认为你也可以使用multimethods。这是clojure的其他多态策略,可能适用于您的用例,因为您只想实现单个方法(save-data
)。
;; set up a config map
(def config {:logger :db-logger)
;; set up the dispatch function to read the logger from the config map
(defmulti save-data (fn [] (:logger config))
;; define methods as required - database logging
(defmethod save-data :db-logger []
(println "Save to database"))
;; some other logging - can be in another file
(defmethod save-data :other-logger []
(println "Save to other thing"))
注意:我对Clojure还不熟悉 - 所以我不确定这是否是使用多方法的“正确”方法。我见过的大多数例子都是关于参数类型的,而不是配置设置。任何专家,如果我的想法错误,请纠正我。