This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-08-16
Channels
- # announcements (3)
- # beginners (104)
- # boot (18)
- # calva (1)
- # cider (43)
- # cljs-dev (45)
- # cljsrn (2)
- # clojure (29)
- # clojure-dev (10)
- # clojure-europe (2)
- # clojure-italy (117)
- # clojure-nl (17)
- # clojure-spec (56)
- # clojure-uk (41)
- # clojuredesign-podcast (12)
- # clojurescript (35)
- # community-development (6)
- # cursive (27)
- # datomic (12)
- # emacs (9)
- # fulcro (6)
- # graalvm (52)
- # instaparse (6)
- # klipse (3)
- # leiningen (11)
- # lumo (1)
- # off-topic (16)
- # pathom (31)
- # re-frame (10)
- # reagent (26)
- # reitit (3)
- # shadow-cljs (67)
- # sql (4)
- # tools-deps (1)
Looking at the latest blog post about spec2: (s/valid? ::s {::f "Bugs" ::l "Bunny" ::x 10} {:closed #{::s}})
.
Does this mean that if ::f
is also a map then in order to close it the user will have to explicitly put it into set too? I.e.: (s/valid? ::s {::f {:a 1 :b 2} ::l "Bunny" ::x 10} {:closed #{::s ::f}})
. If yes, then it seems to be inconvenient for cases with nested maps because when validating a top map I don't want to remember and manually specify the "closed-ness" of all the maps used in validation of every particular key.
Yes, that’s what it means, but it doesn’t preclude some kind of :all setting
I see, thanks. I was wondering how easy it will be to migrate my current codebase to this approach. As currently the knowledge of closedness is tied to each spec (I have a custom macro: (sp/speced-keys :closed? true :req ...)
). And "parent" specs are not aware of this. :all
is fine if all the specs are closed but will not work in case some specs are closed and others are open.
e.g.
::foo = {::a <vector of closed ::x maps> ::b <open ::y map>}
(s/valid? ::foo myfoo {:closed ???})
Keep in mind also that s/keys itself is being replaced with s/schema and s/select
The closed checking is currently implemented only in s/schema, not s/keys
I’ve got this use-case: I’ve got a couple of macros/fns that I use to dynamically create a few “concepts” and associated helper fns (stuff like serialization/deserialization etc). As part of that I’m also creating specs. I’m looking at spec-alpha2 and getting stuck wanting to do something like this:
(s/register k (s/spec (fn [x] ..something using a captured local value..)
This doesn’t fly, the local value (from e.g. an encapsulating let form) ends up not scope captured as I’d expect and instead breaks everything. Any tips how I can accomplish what I need?
the (fn [x] ...)
part here is a symbolic form (not evaluated)
so if you want to use a local value, you need to do something to construct the right symbolic form
you could for example use
`( ... ~foo ... )
ah. ok. i’ll give that a go. the symbol stuff still doesn’t really compute very well with me - it feels like even though spec2 allows being driven by code (as opposed to manual s/def’s), I still don’t find that I’m able to do so doing things the way I expect. The macros still “get in the way” for me a lot of the time.
there are no macros involved in your code above. how can they be in the way?
well I guess s/spec
can you share more of your code?
what is entity?
I guess a symbol? kw?
and in how does this not work? error or spec doesn't do what you expect?
is there some reason you're using s/spec and not s/spec* in last line?
I think you'd want the latter there
try spec* in that last line
(sorry, for screenshots - I don’t have slack access on a remote machine where the code is and can’t copy across)
that's actually a bug in spec 2 function explication
the [x] in the fn is getting ns'ed
well, maybe
in that fn, instead of x
can you do ~'x
everywhere?
I'm not sure if the error here is in your expansion or inside spec 2
cool. that compiles at least, so hoping that means I’m on my way. wont be able to confirm overall functionality without some more work.
basically you're fixing this issue:
user=> `(fn [x] (+ x 1))
(clojure.core/fn [user/x] (clojure.core/+ user/x 1))
I have seen places where spec 2 has trouble with this, but here I think it's in your expansion
the code you now have is not using any macros and there is no "magic" here - it's just passing forms to functions
I think that macro+adapt-spec wrapper was a trial and error solution to similar issue I had with passing in a fn (e.g. string?). if I already had the fn and not the symbol pointing to the fn at the time I want to s/register
I couldn’t work out any way to proceed.
btw, that seems to get me back on track and define the sort of spec I have in mind. thanks a lot for the help - and let me know if you want any more info in terms of it being me vs spec2.
if you already have a function object, then you can't go through the symbolic API (spec*)
as it's not a symbol
but you can directly create a spec object that implements the protocol
w/the caveat that you're not going to be able to s/form or nest that kind of thing in other symbolic forms
which is true to some degree in spec 1 too
yeah. compared to a more data driven API both spec1 and spec2 throws up some speed bumps if one is generating specs by code. but spec2 seems to have enough flex to make it possible to get what I need even if it’s not yet intuitive to me to work in the symbolic space (as compared to more data composition).
so I’m a bit split on the API so far. it doesn’t feel like “normal” clojure when one comes at it from generating specs in code. however, it does compose fine as long as you’re manually spec’ing things. net-net I’d love a more data-driven approach. I’ve seen https://github.com/metosin/spec-tools/blob/master/docs/02_data_specs.md and perhaps what I’m looking for is doable on top of the symbolic api.
well there is now a map-focused format as well (as of last week)
that is almost certainly going to change formats so I wouldn't touch it yet
{:clojure.spec/op `s/keys
:req (conj (map first required) ::entity-type)
:opt (map first optional)}
is something you could pass to s/spec* for example and get the identical spec
and there is an s/expand-spec that can do form->map
but this should be much more amenable to doing spec->map->transform->spec type things
there are now 3 or 4 different ways to tap into spec creation/transformation and we're looking at some meta stuff on top of that which might make some of them more accessible, but really there's a lot of options now