简体   繁体   中英

Clojure Spec - Register a spec pointing at another spec

Could someone shed a light on the following behavior please?

Let's assume I have this namespace with a spec:

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

Now I want to reuse this spec.

(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

When exercising the last spec, I get an error:

(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

However, if I redef the ::dir spec usinig s/register and s/get-spec instead of s/def , no problem:

(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

I'm assuming, from the error message, that with s/def , spec resolves ::dir as the literal ::su/text keyword instead of the associated spec.

1) Why?
2) Is s/register + s/get-spec an appropriate solution?

I'm trying to reuse a "utility" spec in a few places under domain specific names.

FWIW, I'm using spec-alpha2 in order to build specs dynamically and benefit from schema + select .

Aliasing specs like (s/def::dir::su/text) is not currently working in spec 2, which is still a work in progress.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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