Placing this under the Beginners section because I’m completely new to spec.
What’s the difference between s/and
& s/merge
and when should I choose one over the other?
Placing this under the Beginners section because I’m completely new to spec.
What’s the difference between s/and
& s/merge
and when should I choose one over the other?
s/and
will check that the map you have is a valid of both the map specs. Like it’ll check if it’s valid to the first spec, and if true, it’ll check if it’s also valid of the other spec. While s/merge
will check that the map you have is valid to a union of their required and optional keys.
Since keys spec are open, I think when it comes to validating they’re pretty much the same. But when it comes to using the spec for generating sample maps that satisfy it, s/merge
will be able to create a proper generator, while s/and
might struggle and require you to provide a custom generator for it. So in general, I’d say use s/merge
for maps, so anytime you have a s/and
that is only anding map specs, prefer s/merge
over it. Use s/and
when one of the spec involved is not a map spec.
Another important difference is that with s/and
, the conformed value from the first spec flows through the remaining predicates/specs. With s/merge
the original value is used for each spec.
Thanks guys,
I’m working through the website material and am currently looking at this section: https://clojure.org/guides/spec#_a_game_of_cards
I wondered how I would use spec to catch cheaters in the model, so I came up with this:
(defn no-cheaters?
"Returns true if there are no duplicate cards in the game"
[{players ::players deck ::deck}]
(->
concat
(reduce deck (map ::hand players))
count (== 52)))
(s/def ::game
(s/and
no-cheaters?
(s/keys :req [::players ::deck])))
;; test
(s/explain ::game
{::deck (drop 2 deck)
::players [{::name "Kenny Rogers"
::score 100
::hand (take 2 deck)}]})
;; prints "Success!"
(s/explain ::game
{::deck (rest deck)
::players [{::name "Kenny Rogers"
::score 100
::hand (take 2 deck)}]})
;; .... - failed: no-cheaters? ...
This works with no-cheaters?
as the first or second argument to s/and
, but using s/merge
instead does not work. Based on what you’ve told me I don’t understand why.
merge
is for merging s/keys
specs – it can’t be used with a predicate (like no-cheaters?
). That’s what @didibus was saying about when to use s/and
vs s/merge
.
Ah, thanks for clearing that up!
This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.