繁体   English   中英

为所有键clojure相同的“:or”值

[英]clojure same “:or” value for all keys

我定义了一个包含一堆字段的记录-其中一些是经过计算的,有些不直接映射到我正在提取的JSON数据中的键。 我正在为此编写一个工厂函数,但是我想拥有一个明智的默认值/未找到的值。 有没有更好的方法来解决:or [field1 "" field2 "" field3 "" field4 ""...] 我可以写一个宏,但是如果不需要的话,我宁愿不写。

在构造函数中用于实现默认值的共有三种惯用法。

  1. :or破坏

    例:

     (defn make-creature [{:keys [type name], :or {type :human name (str "unnamed-" (name type))}}] ;; ... ) 

    当您要指定默认内联时,这很有用。 另外,它允许在:or映射中让let样式绑定,其中根据:keys向量对kv进行排序。

  2. 合并

    例:

     (def default-creature-spec {:type :human}) (defn make-creature [spec] (let [spec (merge default-creature-spec spec)] ;; .... )) 

    当您要在外部定义默认值,在运行时生成默认值和/或在其他地方重用它们时,这很有用。

  3. 简单or

    例:

     (defn make-creature [{:keys [type name]}] (let [type (or type :human) name (or name (str "unnamed-" (name type)))] ;; ... )) 

    这与:or析构函数一样有用,但是仅评估实际需要的默认值,即,在计算默认值会增加不必要的开销的情况下,应使用它。 (我不知道为什么:or评估所有默认值(从Clojure 1.7开始),所以这是一种解决方法。

如果您确实希望所有字段都使用相同的默认值,并且它们确实必须不同于nil ,并且不想再次写下来,那么可以通过在空实例上调用keys来获取记录字段,然后构造一个映射,将默认值与实际值合并:

(defrecord MyFancyRecord [a b c d])

(def my-fancy-record-fields (keys (map->MyFancyRecord {})))
;=> (:a :b :c :d)

(def default-fancy-fields (zipmap my-fancy-record-fields (repeat "")))

(defn make-fancy-record [fields]
  (map->MyFancyRecord (merge default-fancy-fields
                             fields)))

(make-fancy-record {})
;=> {:a "", :b "", :c "", :d ""}

(make-fancy-record {:a 1})
;=> {:a 1, :b "", :c "", :d ""}

要获取记录字段的列表,您还可以在记录类上使用静态方法getBasis

(def my-fancy-record-fields (map keyword (MyFancyRecord/getBasis)))

getBasis不是公共记录api的一部分,因此无法保证将来的clojure版本中不会将其删除。现在,clojure和clojurescript中都提供了它,其用法在“ Chas Emerick的Clojure编程,Brian Carper中进行了解释,“克里斯托夫·格兰德(Christophe Grand)”,并且在讨论如何从记录中获取密钥的讨论中也提到了这一点 。因此,由您决定使用它是否是一个好主意)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM