Fork me on GitHub
#clojure-spec
<
2019-03-30
>
didibus17:03:17

How would you spec the following: [:keyword1 '(:one :or) '(:more :lists) :keyword2 '(:one :or) '(:more :lists)] where each pair of :keywordN '(:one :or) '(:more :lists) is optional?

didibus17:03:44

I tried:

(s/cat :keyword1-pair (s/?
                  (s/cat :keyword1 #{:keyword1}
                         :keyword1-lists (s/+ list?)))
         :keyword2-pair (s/?
                 (s/cat :keyword2 #{:keyword2}
                        :keyword2-lists (s/+ list?))))
But it doesn't work.

didibus17:03:43

Nevermind, it does work. I had a typo.

didibus17:03:56

I have another question though. It seems that conform evaluates the forms?

didibus17:03:38

Basically, my above spec is for a macro. And I expect the lists to be code forms. Then I call conform to get it conformed, but it seems to evaluate the forms.

didibus17:03:12

(defmacro foo [& bar]
  (s/conform ::my-spec bar))

(foo [:keyword1 (+ 1 1)])
Hum... Unless its evaluated on the print.

didibus17:03:06

Ah yes, nevermind again

seancorfield21:03:03

@alexmiller I'm trying the latest Spec2 and running into a new failure

(s/defop length-limited-string
  "Given n return a spec for a string that is less then n characters
  long."
  [n]
  (s/and string? #(>= n (count %)))) 
;=> #'ws.billing.specs/length-limited-string
(s/def :wsbilling/braintree-id (s/nilable (length-limited-string 64))) 
;=> :wsbilling/braintree-id
(s/def :wsbilling/risk-id :wsbilling/braintree-id)
;=> :wsbilling/risk-id
(s/get-spec :wsbilling/braintree-id)
;=> #object[clojure.spec_alpha2.impl$nilable_impl$reify__12249 0x689396e2 "clojure.spec_alpha2.impl$nilable_impl$reify__12249@689396e2"
(s/get-spec :wsbilling/risk-id)
;=> nil
This worked fine on the last version I tried, and that last s/get-spec call returned a spec, as expected, not nil.

seancorfield21:03:50

If I change :wsbilling/risk-id to

(s/def :wsbilling/risk-id (s/spec :wsbilling/braintree-id))
then it works.

seancorfield21:03:02

Unfortunately we have a lot of specs that are defined as aliases of other specs. I happened to spot this one because we have a test that verifies every key in a related spec has a spec defined for it...

seancorfield21:03:16

Ah, it looks like that spec exercises and conforms just fine, it's only get-spec that "fails" by returning nil.

seancorfield21:03:21

OK, it looks like we used to call s/spec in these cases with Spec1, but that stopped working in Spec2 with the API split into symbolic specs and spec values, so I changed it to s/get-spec and checked it returned non-`nil`. But what I probably should have done was used s/form instead which seems to do the right thing in Spec2. It still seems surprising that s/get-spec returns nil for the case above tho'...

Alex Miller (Clojure team)22:03:37

I know why you’re seeing that

seancorfield23:03:06

Is it a bug or should I just not be doing it that way?

seancorfield23:03:35

(I have almost everything passing again on Spec2 -- still trying to track down one failure in one of our newer apps)

seancorfield23:03:28

OK, everything passes. The only change I had to make was that get-spec issue (in three places).

seancorfield23:03:47

I'll take a break for a bit and then start looking at schema/`select`...