Установка значений по умолчанию в clojure defn - PullRequest
0 голосов
/ 24 ноября 2018

Я супер новичок в clojure и пытаюсь установить значения ошибок для args в функции clojure.Это то, что у меня так далеко:

(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 соответственно.

Однако всякий раз, когда я не отправляю ни один из этих аргументов в get-user-projects-by-user-id, (println sort filtersразмер смещения): ноль ноль ноль ноль.

Как установить для них значения по умолчанию, которые я хочу?

Ответы [ 2 ]

0 голосов
/ 26 ноября 2018

Существует несколько способов предоставления необязательных аргументов и их значений по умолчанию.Какой из них выбрать, зависит от того, как вы хотите предоставить эти необязательные аргументы для вызова функции.

Строго последовательные аргументы

Ваши аргументы уже упорядочены путем уменьшения вероятности их установки.Вы хотите иметь возможность вызывать функцию следующим образом (при условии, что тело функции 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])))

Это немного утомительно в определении функции, и вы должны позаботиться о рефакторинге, чтобы сохранить правильные значения по умолчанию.

Необязательные аргументы в качестве карты

Вы можете использовать деструктурирование в векторе аргументов, чтобы разрешить передачу карты с дополнительными аргументами.Это позволяет передавать их в любом порядке: вы можете переопределить 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]
0 голосов
/ 24 ноября 2018

Здесь есть 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, я думаю):

(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
...