有人可以阐明以下行为吗?
假设我有一个带有规范的命名空间:
(ns user.specs
(:require [clojure.alpha.spec :as s]
[clojure.alpha.spec.gen :as gen]
[clojure.string :as str]))
# Non-blank string of 20 to 50 ascii chars.
(s/def ::text (s/with-gen
(s/and string? #(not (str/blank? %)))
#(gen/such-that
(complement str/blank?)
(gen/fmap
clojure.string/join
(gen/vector
(gen/char)
20 50)))))
现在我想重用这个规范。
(in-ns 'user)
(require '[user.specs :as su])
=> nil
(def kws [::dir
::ns])
=> #'user/kws
(s/def ::dir ::su/text)
=> :user/dir
(s/def ::ns string?)
=> :user/ns
(s/register ::spec (s/schema* kws))
=> :user/spec
执行最后一个规范时,出现错误:
(s/exercise ::spec)
Error printing return value (IllegalArgumentException) at clojure.core/-cache-protocol-fn (core_deftype.clj:583).
No implementation of method: :conform* of protocol: #'clojure.alpha.spec.protocols/Spec found for class: clojure.lang.Keyword
但是,如果我重新定义::dir规范使用s/register而s/get-spec不是s/def,没问题:
(s/register ::dir (s/get-spec ::su/text))
=> :user/dir
(s/exercise ::spec)
=>
([#:user{:dir "teôÆ>EüáéNj¬u}zþs²DÍ$", :ns ""}
#:user{:dir "teôÆ>EüáéNj¬u}zþs²DÍ$", :ns ""}]
[#:user{:dir ":éû,@Î|)Q«óCS\t´ÿ4ÚÝܺ»Ân5Zq", :ns ""}
#:user{:dir ":éû,@Î|)Q«óCS\t´ÿ4ÚÝܺ»Ân5Zq", :ns ""}]
... elided
我假设,从错误消息中,使用s/def, spec 解析::dir为文字::su/text关键字而不是关联的规范。
1)为什么?
2) s/register+s/get-spec是一个合适的解决方案吗?
我正在尝试在域特定名称下的几个地方重用“实用程序”规范。
FWIW,我正在使用 spec-alpha2 来动态构建规范并从schema+中受益select。