As soon as you introduce the s/and, you have dropped out of regex land and 
into a predicate. You are then matching something in a new nested regex 
inside the and like:  [[::even 4]]. To stay within the top-level regex and 
supply extra predicates, use s/& instead:

(s/def ::options
  (s/& (s/keys* :opt-un [::even]) (fn [m] (not (contains? m :odd)))))

user=> (s/conform ::options [:even 2])
{:even 2}
user=> (s/conform ::options [:even 2 :foo 5])
{:even 2, :foo 5}

user=> (s/explain ::options [:even 3])
val: () fails spec: :user/options predicate: (& (* (cat :clojure.spec/k 
keyword? :clojure.spec/v :clojure.spec/any)) :clojure.spec/kvs->map (keys 
:opt-un [:user/even])),  Insufficient input
user=> (s/explain ::options [:even 2 :odd 3])
val: {:even 2, :odd 3} fails spec: :user/options predicate: (fn [m] (not 
(contains? m :odd)))


On Wednesday, June 29, 2016 at 5:19:09 PM UTC-5, puzzler wrote:
>
> I'm having trouble spec'ing out something like this, a function that takes 
> an integer as an input followed by a series of optional keyworded args.  
> :even is an allowed optional keyword, but we definitely want to forbid :odd 
> as an optional keyword.
>
> (s/def ::even even?)
> (s/def ::options 
>   (s/and 
>     (s/keys* :opt-un [::even])
>     (fn [m] (not (contains? m :odd)))))
>     
> (defn f [n & {:as options}] nil)
> (s/fdef f :args (s/cat :integer int? :options ::options))
> (stest/instrument `f)
>
> This doesn't work at all and gives all sorts of errors when f is called 
> with any input. I believe it is because the use of s/and in the definition 
> of ::options interferes with the ability of ::options to be "flattened" 
> into the s/cat definition.
>
> My reasoning:
> ::options correctly validates [:even 2] and rejects [:even 2 :odd 3] and 
> [:even 3].  
> If I omit the s/and and the second clause so that it reads:
> (s/def ::options (s/keys* :opt-un [::even]))
> this also behaves as expected.
>
> So my conclusion is that the s/and is interfering with the ability of 
> s/keys* to sit within the s/cat definition.
>
> How does one solve this problem?
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to