我想在clojure
中创建一个工厂,其中创建者的参数数量在运行时会有所不同。
例如:
(defn create-long-document [direction]
(str "long document " direction))
(defn create-short-document[]
"short document")
(def creator-map {
:english create-short-document
:hebrew create-long-document
})
(def additional-arg-map {
:english nil
:hebrew "rtl"
})
(defn create-document [language]
(let [creator (language creator-map) arg (language additional-arg-map)]
(if arg (creator arg) (creator))))
(println (create-document :hebrew)); long document rtl
(println (create-document :english)); short document
我正在寻找一种优雅方式来重写create-document
的正文。我想摆脱if
。也许通过引入智能宏?
请与您分享想法。
答案 0 :(得分:2)
我建议您将其他参数指定为集合:
(def additional-arg-map {
:english []
:hebrew ["rtl"]})
然后,您可以在创建文档功能中使用apply,例如:
(defn create-document [language]
(let [creator (creator-map language)
args (additional-arg-map language)]
(apply creator args)))
请注意,如果您希望允许调用者提供特定的额外参数,那么替代(或可能是互补的?)方法将是定义变量arity函数,例如:类似的东西:
(defn create-document
([language]
.....handle no argument.....)
([language arg]
.....handle 1 argument.....)
([language arg & more-args]
.....handle more than one argument.....))
答案 1 :(得分:2)
我猜multimethods会产生更干净的代码。使用您写的create-long-document
和create-short-document
的相同定义:
; change identity to something more sophisticated
; if you want sanity checks on input:
(defmulti create-document identity)
(defmethod create-document :default [lang] "language not supported")
(defmethod create-document :english [lang] (create-short-document))
(defmethod create-document :hebrew [lang] (create-long-document "rtl"))
然后,create-document
将按预期工作:
user=> (create-document :hebrew)
"long document rtl"
user=> (create-document :english)
"short document"
user=> (create-document :italian)
"language not supported"
通过这种方式,调度逻辑由multimethods API提供,无需编写自己的调度函数。这种方法的好处是可扩展性:支持新语言只需要一个新的defmethod
。
答案 2 :(得分:1)
我想这可能很简单:
(defn create-long-document [direction]
(str "long document " direction))
(defn create-short-document[]
"short document")
(def creator-map {
:english #(create-short-document)
:hebrew #(create-long-document "rtl")
})
(defn create-document [language]
((creator-map language))
)