Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Clojure中,如何编写具有可变参数数的工厂_Clojure - Fatal编程技术网

在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

我想在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文档的主体。我想摆脱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的每个实例中复制代码,我很确定你能够将公共部分分解成一些外部函数