簡體   English   中英

如何在Clojure中為記錄中的字段設置默認值?

[英]How to set default values for fields in records in Clojure?

我在Clojure中創建記錄,並希望使用默認值設置一些字段。 我怎樣才能做到這一點?

使用構造函數。

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

當然有各種各樣的變化。 例如,您可以要求某些字段是非可選字段而不是默認字段。

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

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

因人而異。

通過擴展映射構建初始值時,可以非常輕松地將初始值傳遞給記錄:

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

在有了相同的問題之后,我最終使用宏將defrecord和工廠函數包裝成單個定義。

宏:

(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"}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM