This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-10-22
Channels
- # 100-days-of-code (3)
- # announcements (7)
- # beginners (147)
- # cider (22)
- # cljdoc (24)
- # cljs-dev (71)
- # cljsrn (8)
- # clojars (3)
- # clojure (45)
- # clojure-conj (11)
- # clojure-dev (1)
- # clojure-italy (21)
- # clojure-nl (2)
- # clojure-spec (76)
- # clojure-sweden (2)
- # clojure-uk (100)
- # clojurebridge (3)
- # clojurescript (15)
- # cursive (7)
- # data-science (2)
- # datomic (7)
- # emacs (9)
- # events (2)
- # figwheel-main (4)
- # fulcro (117)
- # jobs (2)
- # jobs-discuss (21)
- # leiningen (184)
- # nyc (4)
- # off-topic (50)
- # planck (6)
- # re-frame (14)
- # reagent (25)
- # ring-swagger (5)
- # shadow-cljs (96)
- # spacemacs (5)
- # sql (26)
- # tools-deps (12)
- # uncomplicate (1)
- # yada (3)
@misha can you make it much shorter though? you could skip the my-app.schema
part, sure
the spec kw length you have in example - is ok as is I think, but: I'd used that length for something more descriptive/convenient, so you would not feel the nee to alias it away, and avoid entire issue with dependencies.
and when you don't need to use aliases, you just need to make sure all specs are :required at the app entry points. no need to import those all over the place, as those are accessible from global registry, which you can get away initing just once.
it is helpful to think about spec-kw namespaces as db table names, not as code namespaces those happen to be defined in. Otherwise specs would not survive first mild refactoring
although I was going to put those spec in a schema
namespace, not next to code, so there isnāt a big difference there between that and the ātable namesā approach youāre suggesting
you receive map as rest response. it contains "...schema.../..." keys. what a waste of electricity
then, imagine, you now need to move them around in the code. ā you either loose all your aliases, or break backward compatibility. ouch
I mean, isn't one of the proposals of namespaces in keys that you don't rename them, unless you are planning to make a breaking change in a published API, and you should weigh consequences of that pretty seriously?
so I guess it would still be fine to namespace-qualify collection specs (i.e. (s/def ::person (s/keys ...
), but you would avoid such long namespace qualification for key specs
And gzip and things like Transit reduce the waste of electricity somewhat.
there is an ugly workaround, (create-ns 'foo.bar.baz) (alias 'fbb 'foo.bar.baz), but it is meh.
because collection specs are essentially a codebase-level notion, whereas keys may be sent over the network, stored, etc
@andy.fingerhut imagine "...schema..." suffix in every sql column or table name
My mind isn't reeling yet, but I haven't lived and breathed it day in and out, either. Six of one, half dozen of another.
and yes, you should not rename those, if they are public outside the app code. therefore if you suddenly need to move definitions elsewhere - file ns and spec ns do not match anymore.
why don't they appear?
{:my-app.schema/persons [{:my-app.schema.person/first-name "joe"}]}
also, if you don't preserve ns for js clients - you are missing out as well: "my-app.schema.person/first-name" e.g. cheshire prints qualified keywords this way by default
so, i.e., in this case, would you name things as:
(ns my-app.schema)
(s/def :schema/person (s/keys :req [:person/first-name :person/friends]))
(s/def :person/first-name string?)
(s/def :person/friends (s/coll-of :schema/person))
?well, if you are confident you will not have external person - it might be ok. otherwise, prepending with a short project codename would not hurt. but I'd think twice before adding anything between codename and entity name
if you are in a corporate setting, you are probably required to add at least full org name instead or in addition to project name: :com.cognitect/person
:com.cognitect.project/person
Is it possible to have clojure.spec not throw exceptions on fdef violations, but only print āfdef error, line so and soā and then continue as always?
https://github.com/funcool/cats/blob/master/src/cats/monad/either.cljc#L48
Is there anyway I can spec such a type (`Either left right`) on a per-function basis? So for example, I might want to add a spec to a function saying it returns either a string?
or a number?
, etc
Always good to remember that specs are not types. You can use s/or to spec an alternative but thatās not going to be generic.
(I realise this sounds similar to what the s/or
spec does, but I need to work with records here, as defined in cats)
is there any way I can do something generic in this case @alexmiller?
You can treat records as maps with unqualified keys and use :req-un to specify specs on keys
But, not generically
For specific functions, you could define a :fn spec that checks a relationship between args and ret
@alexmiller but then Iāll have to make qualified keys for every possible way there is to use the Either record. As far as I know there is no way to directly define an unqualified map spec, right? i.e. nothing like (s/foo :left string? :right number?)
which would accept a map with keys :left and :right matching the specs
(s/valid?
(s/cat
:left (s/tuple #{:left} string?)
:right (s/tuple #{:right} number?))
{:left "a" :right 1})
=> true
this s/cat assumes maps are ordered, which they are not. in fact, in latest spec, you will get false here.
s/cat can only be used with sequential? collections now
@hmaurer there is also more legal way, where map-of will permit only 1 map-entry:
(s/or
:left (s/map-of #{:left} string?)
:right (s/map-of #{:right} number?))
(s/def :cats/left (s/or :string string? :exception #(instance? Exception %)))
(s/def :cats/right any?)
(s/def :cats/monad (s/keys :req-un [(or :cats/left :cats/right)]))
(s/valid? :cats/monad {:left (ex-info "foo" {})})
(s/valid? :cats/monad {:left "a"})
(s/valid? :cats/monad {:right [:bar]})
=> true
=> true
=> true
Right, but then for every potential use of Either i need to define a keyword spec, i.e. :some.specific/right
or, if you will have specific spec for wrapped value anyway, you can unpack in custom predicate, and s/and with that
@hmaurer there is also more legal way, where map-of will permit only 1 map-entry:
(s/or
:left (s/map-of #{:left} string?)
:right (s/map-of #{:right} number?))
@hmaurer I had this problem continually, where I have a spec key but I need to narrow it further in specific contexts without changing the key name
(s/def :either/either (s/keys ::req-un [:either/left :either/right]))
is the basic notion of "either"
(s/spec (s/merge :either/either (keys+ :req-un [:either/left :either/right] :conf {:either/left number? :either/right string?}))
that would be "this is an :either/either, but some of the keys use a different generator and predicate"
https://gist.github.com/favila/ab03ba63e6854a449d64d509aae74618 if you are interested
(defmacro speceither [left-spec right-spec]
`(s/or
:left (s/map-of #{:left} ~left-spec :min-count 1)
:right (s/map-of #{:right} ~right-spec :min-count 1)))
(s/valid?
(speceither string? (s/coll-of number?))
{:right [1 2 3]})
=> true
conformed values are garbage though, but exercise works just finethanks @favila! Iāll read this up. Does this spec give nice errors / generators / conforming?