在Clojure中,如何编写具有可变参数数的工厂
我想在clojure中创建一个工厂,其中创建者的参数数量在运行时有所不同 例如:在Clojure中,如何编写具有可变参数数的工厂,clojure,Clojure,我想在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
(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文档的主体。我想摆脱if。也许通过引入智能宏
请分享您的想法。我建议将您的附加参数指定为集合:
(def additional-arg-map {
:english []
:hebrew ["rtl"]})
然后,您可以在“创建文档”功能中使用以下内容:
(defn create-document [language]
(let [creator (creator-map language)
args (additional-arg-map language)]
(apply creator args)))
(defn create-document
([language]
.....handle no argument.....)
([language arg]
.....handle 1 argument.....)
([language arg & more-args]
.....handle more than one argument.....))
请注意,是备选方案还是补充方案?如果您想允许调用方提供特定的额外参数,可以定义一个变量arity函数,例如:
(defn create-document [language]
(let [creator (creator-map language)
args (additional-arg-map language)]
(apply creator args)))
(defn create-document
([language]
.....handle no argument.....)
([language arg]
.....handle 1 argument.....)
([language arg & more-args]
.....handle more than one argument.....))
我建议将附加参数指定为集合:
(def additional-arg-map {
:english []
:hebrew ["rtl"]})
然后,您可以在“创建文档”功能中使用以下内容:
(defn create-document [language]
(let [creator (creator-map language)
args (additional-arg-map language)]
(apply creator args)))
(defn create-document
([language]
.....handle no argument.....)
([language arg]
.....handle 1 argument.....)
([language arg & more-args]
.....handle more than one argument.....))
请注意,是备选方案还是补充方案?如果您想允许调用方提供特定的额外参数,可以定义一个变量arity函数,例如:
(defn create-document [language]
(let [creator (creator-map language)
args (additional-arg-map language)]
(apply creator args)))
(defn create-document
([language]
.....handle no argument.....)
([language arg]
.....handle 1 argument.....)
([language arg & more-args]
.....handle more than one argument.....))
我想这会导致代码更干净。使用与您编写的“创建长文档”和“创建短文档”相同的定义:
; 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"))
然后,“创建文档”将按预期工作:
user=> (create-document :hebrew)
"long document rtl"
user=> (create-document :english)
"short document"
user=> (create-document :italian)
"language not supported"
通过这种方式,调度逻辑由multimethods API提供,无需编写自己的调度函数。这种方法的优点是可扩展性:支持一种新语言只需要一种新的defmethod。我想这会导致代码更干净。使用与您编写的“创建长文档”和“创建短文档”相同的定义:
; 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"))
然后,“创建文档”将按预期工作:
user=> (create-document :hebrew)
"long document rtl"
user=> (create-document :english)
"short document"
user=> (create-document :italian)
"language not supported"
通过这种方式,调度逻辑由multimethods API提供,无需编写自己的调度函数。这种方法的优点是可扩展性:支持一种新语言只需要一种新的defmethod。我想它可以简单到:
(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))
)
我想这可能很简单:
(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))
)
无需允许调用方提供特定的额外参数。在我的例子中,所有额外的参数必须对调用方隐藏。不需要允许调用方提供特定的额外参数。在我的例子中,所有额外的参数必须对调用方隐藏。这不是一个优雅的解决方案,因为创建者映射知道它定义的函数的调用方式。creatormap和createdocument之间存在耦合:例如,如果createdocument想要放弃额外的参数,则还需要修改creatormap。在某些地方,您需要进行耦合。在代码中,它位于createdocument函数本身。在现实世界中,没有任何代码是完全没有耦合的。这不是一个优雅的解决方案,因为创建者映射知道它定义的函数的调用方式。creatormap和createdocument之间存在耦合:例如,如果createdocument想要放弃额外的参数,则还需要修改creatormap。在某些地方,您需要进行耦合。在代码中,它位于createdocument函数本身。在现实世界中,没有任何代码是完全没有耦合的。这种方法的问题是,如果create document的代码变得更丰富,你必须在multimethod的每个实例中复制代码。我很确定你能够将公共部分分解为一些外部函数。这种方法的问题是,如果create document的代码变得更丰富一点,你必须在multimethod的每个实例中复制代码,我很确定你能够将公共部分分解成一些外部函数