Как установить значения по умолчанию для полей в записях в Clojure? - PullRequest
14 голосов
/ 12 апреля 2011

Я создаю записи в Clojure и хотел бы установить для некоторых полей значение по умолчанию. Как я могу это сделать?

Ответы [ 3 ]

21 голосов
/ 12 апреля 2011

Используйте функцию конструктора.

(defrecord Foo [a b c])

(defn make-foo
  [& {:keys [a b c] :or {a 5 c 7}}]
  (Foo. a b c))

(make-foo :b 6)
(make-foo :b 6 :a 8)

Конечно, существуют различные варианты.Например, вы можете требовать, чтобы некоторые поля были необязательными и не имели значений по умолчанию.

11 голосов
/ 12 апреля 2011

Вы можете довольно легко передать начальные значения записи, когда создаете ее через карту расширений:

(defrecord Foo [])

(def foo (Foo. nil {:bar 1 :baz 2}))

В свете этого я обычно создаю функцию конструктора, которая объединяет некоторые значения по умолчанию (которые вы можете переопределить по своему усмотрению):

(defn make-foo [values-map]
  (let [default-values {:bar 1 :baz 2}]
    (Foo. nil (merge default-values values-map))))

(make-foo {:fiz 3 :bar 8})
=> #:user.Foo{:fiz 3, :bar 8, :baz 2}
1 голос
/ 03 июля 2016

После того же вопроса у меня получилось объединить defrecord и factory factory в одно определение с помощью макроса.

Макрос:

(defmacro make-model
  [name args & body]
  (let [defaults (if (map? (first body)) (first body) {})
        constructor-name (str/lower-case (str "make-" name))]
    `(do (defrecord ~name ~args ~@(if (map? (first body)) (rest body) body))
         (defn ~(symbol constructor-name)
           ([] (~(symbol constructor-name) {}))
           ([values#] (~(symbol (str "map->" name)) (merge ~defaults values#)))))))

Использование

(make-model User [firstName lastName] {:lastName "Smith"})
=> #'user/make-user
(make-user {:firstName "John"})
=> #user.User{:firstName "John", :lastName "Smith"}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...