This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-10-11
Channels
- # announcements (6)
- # architecture (9)
- # beginners (120)
- # calva (13)
- # cider (28)
- # clj-kondo (8)
- # cljs-dev (7)
- # clojure (113)
- # clojure-europe (13)
- # clojure-italy (7)
- # clojure-nl (9)
- # clojure-spec (44)
- # clojure-uk (7)
- # clojuredesign-podcast (15)
- # clojurescript (18)
- # cursive (9)
- # data-science (3)
- # datomic (32)
- # defnpodcast (1)
- # events (2)
- # fulcro (6)
- # jobs (1)
- # kaocha (5)
- # london-clojurians (2)
- # luminus (2)
- # nyc (2)
- # off-topic (54)
- # ring (6)
- # shadow-cljs (136)
- # sql (1)
- # testing (2)
- # tools-deps (64)
- # vim (83)
While playing around with spec2 I noticed that I can select keys that are not in the schema:
(s/def ::first-name string?)
(s/def ::last-name string?)
(s/def ::user (s/schema [::first-name ::last-name]))
(s/select ::user [:first-name])
Is this expected behavior? From reading the docs on select
I expected it to select from the schema and provide a more restrictive spec. Is this the wrong way of thinking about it?@mattparker I think it's a known issue (I think I remember Alex mentioning this).
ah ok. Thanks!
It would probably be nice for the above to throw an exception (that :first-name
isn't present in the schema).
schemas and selects are both open, so this is the expected behavior
if doing closed spec checking, it would make sense for that to error (I'm not at a repl but I suspect it doesn't right now due to some lingering work there)
Ah, that might be what I'm thinking of...
select is about requirements
you must supply ... , not you can only supply
user=> (s/explain (s/select ::user [:first-name]) {::first-name "Sean"})
#:user{:first-name "Sean"} - failed: (fn [m] (contains? m :first-name))
nil
user=>
(so select
can force key presence for things that are not aligned with specs for their values)
wouldn't that easily be achieved by expanding the schema with union?
that would make the first arg what's possible and then the second arg the restrictions
that's not what select is
select tells you what is required in a context
"restrictions" are about negation / closed world
what got me thinking that was in the wiki s/select is a spec op that uses a schema to define the world of possible keys
in this case :first-name
is in the world of possible
well, there's a separate wrinkle here of qualified vs unqualified keys
but I guess what this means is schema is a subset of what's possible
probably this is mostly that I could be better at writing words :)
it's a wiki for an alpha. I definitely don't take it as a contract haha
anything on that wiki is me writing, and not vetted by Rich
thanks for helping me understand!
A question around clojure.spec.test.check/check
for its num-tests
opt.
I’m trying to check how many times a snippet has run based on the print values as below.
(s/fdef foo :args (s/cat :s string?) :ret string?)
(defn foo [s] (prn "s") s)
(s/fdef bar
:args (s/cat :x string?)
:ret (s/fspec :args (s/cat :x string?)
:ret string?))
(defn bar [x]
(prn "x")
(fn [y] (prn "y") y))
(alias 'stc 'clojure.spec.test.check)
(st/check `foo {::stc/opts {:num-tests 1}})
(st/check `bar {::stc/opts {:num-tests 1}})
s => printed 1 time
x => printed 1 time
y => printed 21 times
Could anyone give any insights here that why y
has been printed out 21 times? And is there a way to control the number of tests run for a s/fspec
block?fspecs are validated using their own test.check run
I doubt it's configurable
Thanks for the quick response! That makes sense, will you able to point where that's configured in the source code? It will be really nice if I could configure that, since one of my fspec is running super slow and I don't want it to eat up all my resources.
@stevenz You can re-bind this dynamic var https://github.com/clojure/spec.alpha/blob/master/src/main/clojure/clojure/spec/alpha.clj#L25-L27
@alexmiller hello, I just watched your video from the clojuretree. nice talk! I noticed one thing about the new schema
/ select
thing, in the current spec1, its valid to create anonymous selections, like calling (s/keys)
directly as a parameter or a return value, this possibility seems to be vanished with the requirement to name the things with s/schema
before doing the structural selection with s/select
, did I got that right? if not, is there gonna be a way to define nested selections without having to name it?
There’s no requirement to name either
ok, so the idea is to use like: (s/select [] [{::my/selection [::deep-value]}])
, like this?
well, vector there, but yes
fixed 🙂
cool, thanks for the clarification
schemas can be put in the registry to reuse them, which we think is useful, but not required
selects are probably less useful to put in the registry
yeah, what makes it important to me, is that more and more I'm going in a modeling direction that I don't name groups of things most of the time
instead, just say what "shape" a fn needs directly, so I can get very specific every time
do you think a select with arity 1 makies sense? so it would use empty keyset
I have a map with a ::type
key and a ::tags
key. ::tags
is a map. I want the keys in the ::tags
map to depend on the ::type
of the "top-level" map. Is this possible to spec? e.g., Where the ::tags
map is spec'ed as (s/keys :req [::a])
for ::type ::a
.
{::type ::a
::tags {::a 1}}
It seems like the options are either:
1) restructure the map so the type and tags are at the same level (this won't work because there needs to be a way to get the tags map easily)
2) Copy the ::type
key into the ::tags
map & use multi-spec (this isn't great because the data is redundant)
3) Create a s/and
predicate on the top-level map that checks the ::tags
using multi-spec after assoc
'ing the ::type
onto the ::tags
map. (this feels icky but may be the best way)
4) Unqualify ::tags
(I don't really like this because every other key in the map is qualified. The key :tags
may be used all over the place so finding usages of the key becomes harder therefore making refactoring harder.)