在Clojure Defn中设置默认值

时间:2018-11-24 06:41:47

标签: clojure functional-programming

我对clojure非常陌生,我正在尝试在clojure函数中为args设置故障值。这是我到目前为止的内容:

(defn get-user-projects-by-user-id
([db-conn userid] (get-user-projects-by-user-id db-conn userid (str "asc") nil 10 10))
([db-conn userid sort filters offset size]
      ;;rest of the function

我要完成的工作是,只要该函数未收到排序,过滤器,偏移量或大小,或者为nil / false,它们分别获得默认值“ asc”,nil,10和10

但是,每当我不向用户ID发送任何这些参数到get-user-projects-by-id时,(println排序过滤器偏移量大小)为nil nil nil nil。

如何将它们设置为所需的默认值?

2 个答案:

答案 0 :(得分:2)

在这里我可以想到3种方式:

您的版本:

(defn get-user-projects-by-user-id
  ([db-conn userid] (get-user-projects-by-user-id db-conn userid "asc" nil 10 10))
  ([db-conn userid sort filters offset size]
   (println "arguments: sort:" sort "filters:" filters "offset:" offset "size:" size)))

;; (get-user-projects-by-user-id 'db 'userid)
;; => arguments: sort asc , filters nil , offset 10 , size 10

另一种样式是传递opts参数,该参数是带有所需选项的映射,您可以使用destructuring以方便的方式提供默认值:

(defn get-user-projects-by-user-id-with-opts
  ([db-conn userid]
   (get-user-projects-by-user-id-with-opts db-conn userid nil))
  ([db-conn userid {:keys [sort filters offset size]
                    :or   {sort "asc" offset 10 size 10}}]
   (println "arguments: sort:" sort "filters:" filters "offset:" offset "size:" size)))

;; (get-user-projects-by-user-id-with-opts 'db 'userid)
;; => arguments: sort: asc filters: nil offset: 10 size: 10

;; (get-user-projects-by-user-id-with-opts 'db 'userid {:sort "desc" :offset 20})
;; => arguments: sort: desc filters: nil offset: 20 size: 10

最后,第三种方法有时在较旧的库中使用,该方法是将任意数量的参数传递给您的函数,并在其他参数之后采用可选参数(我想这有点像Python):< / p>

(defn get-user-projects-by-user-id-with-varargs
  [db-conn userid & args]
  (let [arg-map (apply hash-map args)
        {:keys [sort filters offset size]
         :or   {sort "asc" offset 10 size 10}} arg-map]
    (println "arguments: sort:" sort "filters:" filters "offset:" offset "size:" size)))

;; (get-user-projects-by-user-id-with-varargs 'db 'userid)
;; => arguments: sort: asc filters: nil offset: 10 size: 10

;; (get-user-projects-by-user-id-with-varargs 'db 'userid :sort "desc" :offset 20)
;; => arguments: sort: desc filters: nil offset: 20 size: 10

答案 1 :(得分:0)

有几种提供可选参数及其默认值的方法。选择哪个取决于您要如何向函数调用提供那些可选参数。

严格串行参数

您的参数已经通过减小设置参数的可能性进行了排序。您希望能够像这样调用该函数(假设一个println函数体而忽略了nil返回值):

user> (get-user-projects-by-user-id :conn :uid)
[:conn :uid asc nil 10 10]
user> (get-user-projects-by-user-id :conn :uid :sort)
[:conn :uid :sort nil 10 10]
user> (get-user-projects-by-user-id :conn :uid :sort "filter")
[:conn :uid :sort filter 10 10]
user> (get-user-projects-by-user-id :conn :uid :sort "filter" 9)
[:conn :uid :sort filter 9 10]

为此,您可以通过已启动的Arity重载该功能:

(defn get-user-projects-by-user-id
  ([db-conn userid]
   (get-user-projects-by-user-id db-conn userid
                                 (str "asc")
                                 nil
                                 10
                                 10))
  ([db-conn userid sort]
   (get-user-projects-by-user-id db-conn userid
                                 sort
                                 nil
                                 10
                                 10))
  ([db-conn userid sort filters]
   (get-user-projects-by-user-id db-conn userid
                                 sort
                                 filters
                                 10
                                 10))
  ([db-conn userid sort filters offset]
   (get-user-projects-by-user-id db-conn userid
                                 sort
                                 filters
                                 offset
                                 10))
  ([db-conn userid sort filters offset size]
   (println [db-conn userid sort filters offset size])))

函数定义有点繁琐,在重构时必须小心以保持默认值正确。

可选参数作为地图

您可以在参数向量中使用 destructuring 来允许传递带有额外参数的地图。这允许以任何顺序传递它们:您可以覆盖offset,而不必传递sort和其他变量:

(defn get-user-projects-by-user-id-extra-map
  [db-conn userid & [{:keys [sort filters offset size]
                      :or   {sort    "asc"
                             filters nil
                             offset  10
                             size    10}}]]
  (println [db-conn userid sort filters offset size]))

您可以这样使用它:

user> (get-user-projects-by-user-id-extra-map :conn :uid {:offset 9})
[:conn :uid asc nil 9 10]

成对的可选参数

如果您稍微修改解构结构(请注意缺少的[]),则可以无需映射就将可选参数作为键值对传递。当您的函数调用都是显式的时,这通常更容易使用,而当您apply以编程方式收集的额外参数来使用函数时,上一个选项通常会更容易。

(defn get-user-projects-by-user-id-pairs
  [db-conn userid & {:keys [sort filters offset size]
                     :or   {sort    "asc"
                            filters nil
                            offset  10
                            size    10}}]
   (println [db-conn userid sort filters offset size]))

使用它(注意缺少{}):

user> (get-user-projects-by-user-id-pairs :conn :uid :offset 9)
[:conn :uid asc nil 9 10]