我正在学习Clojure并享受它,但发现记录中的不一致让我感到困惑:为什么默认的地图构造函数(map-> Whatever)在创建新记录时检查数据完整性?例如:
user=> (defrecord Person [first-name last-name])
#<Class@46ffda99 user.Person>
user=> (map->Person {:first-name "Rich" :last-name "Hickey"})
#user.Person {:first-name "Rich" :last-name "Hickey"}
user=> (map->Person {:first-game "Rich" :last-name "Hickey"})
#user.Person {:first-game "Rich" :first-name nil :last-name "Hickey"}
我认为Map不需要定义Record定义中的所有字段,也允许包含不属于Record定义的额外字段。另外我理解我可以定义自己的构造函数来包装默认构造函数,然后我认为可以使用:post
条件来检查正确(和全面)的记录创建(没有成功地使其工作)
我的问题是:是否有一种惯用的Clojure方法可以在Map构建记录期间验证数据?而且,这里有关于唱片的东西吗?
谢谢。
答案 0 :(得分:5)
我认为你的综合性要求已经非常具体,所以我所知道的任何内置都无法涵盖这一点。
现在你可以做的一件事就是使用clojure.spec为你的构造函数提供一个s/fdef
(然后对它进行检测)。
(require '[clojure.spec.alpha :as s]
'[clojure.spec.test.alpha :as stest])
(defrecord Person [first-name last-name])
(s/fdef map->Person
:args (s/cat :map (s/keys :req-un [::first-name ::last-name])))
(stest/instrument `map->Person)
(map->Person {:first-name "Rich", :last-name "Hickey"})
(map->Person {:first-game "Rich", :last-name "Hickey"}) ; now fails
(如果为::first-name
和::last-name
定义了规范,那么也会对其进行检查。)
答案 1 :(得分:1)
另一个选项是to use Plumatic Schema来创建一个包装器&#34;构造函数&#34;指定允许键的函数。例如:
{ :foo "hello" :bar :some-kw }
第一行定义了一个只接受以下地图的模式:
(def NameMap {(s/required-key :first-name) s/Str (s/required-key :last-name) s/Str})
(s/defn safe->person
[name-map :- NameMap]
(map->Person name-map))
你的包装器构造函数看起来像:
(s/defn safe->person-2
[name-map]
(assert (= #{:first-name :last-name} (set (keys name-map))))
(map->Person name-map))
或
plugins: [
new CopyWebpackPlugin([
{ from: 'app/assets', to: 'assets' }
])
]