[英]clojure same “:or” value for all keys
我定义了一个包含一堆字段的记录-其中一些是经过计算的,有些不直接映射到我正在提取的JSON数据中的键。 我正在为此编写一个工厂函数,但是我想拥有一个明智的默认值/未找到的值。 有没有更好的方法来解决:or [field1 "" field2 "" field3 "" field4 ""...]
? 我可以写一个宏,但是如果不需要的话,我宁愿不写。
在构造函数中用于实现默认值的共有三种惯用法。
:or
破坏
例:
(defn make-creature [{:keys [type name], :or {type :human name (str "unnamed-" (name type))}}] ;; ... )
当您要指定默认内联时,这很有用。 另外,它允许在:or
映射中让let
样式绑定,其中根据:keys
向量对kv进行排序。
合并
例:
(def default-creature-spec {:type :human}) (defn make-creature [spec] (let [spec (merge default-creature-spec spec)] ;; .... ))
当您要在外部定义默认值,在运行时生成默认值和/或在其他地方重用它们时,这很有用。
简单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.