Fork me on GitHub

If I define specs such as :event/type, it's something that will likely be defined by more projects, so is the best practice to have a fuller namespace such as This will deviate from the shorter form of my Datomic attributes which I don't want to prefix with the organization name all over the place. (I assume specs can collide being in the same process, while in Datomic I control what I put there)


Perhaps the question is about specs of internal vs external data.

Alex Miller (Clojure team)12:11:38

Yes, you should use a sufficiently unique namespace

Alex Miller (Clojure team)12:11:54

But if you control what namespaces you're using, "sufficiently" can be pretty short


Being paranoid, maybe it could be nice to have separate non-default registry instances, or attaching a spec to a key when calling s/keys somehow.


@yonatanel if you're paranoid then you can just use sufficiently unique namespaces


On a similar note, what’s the suggested way to spec a format you didn’t define, that defines the same key with different values/specs… Basically is there an alternative to using s/keys when I have two different specs that share that prefix? Or should I just move the conflicting definitions into different namespaces?


Different namespaces


It just occurs to me that spec can't describe something where a namespaced keyword has varying meaning


gfredericks: that’s the problem I have


Which I imagine is rare


Who subjected you to this


well maybe I don’t have the problem


I mean I can work around it by defining the specs in different namespaces

Alex Miller (Clojure team)15:11:38

If you have that problem, you may be doing it wrong :)


entirely possible

Alex Miller (Clojure team)15:11:20

if you have unqualified keys, then you can deal with this using s/keys and :req-un with different namespaced specs

Alex Miller (Clojure team)15:11:44

if you have qualified keys, then… use the namespaces to differentiate different semantics


alexmiller: yeah I think I just need to define some new namespaces for those extra keys


out of interest is it possible to do (s/def :foo/spec ,,,) and have that work with keys :req-un?


Looks normal....?


Every registered spec has to have a namespace


gfredericks: What I mean is - is the above possible instead of having to create a new namespace e.g. can you do the above instead of needing (ns (s/def ::spec ,,,)


Code namespaces and keyword namespaces are mostly independent


ok that’s what I thought, it’s just not working - presumably for another reason


its ok I fixed it


code blindness


The eternal bug


yup - that’s one thing about software development, you have to be pretty thick skinned as you’re continually told by the computer that “you suck! Another mistake, are you some kinda noob? Oh and another mistake, you really aren’t good enough…” ad-infinitum… I have a hypothesis that this is why people don’t stick it out as a career


you basically have to be a bit of a masochist to stick it out


@rickmoynihan My take on this is that you can't yet have "wonderful" mistakes when programming, unlike art where if you use some new material or do a quick sketch it can still look good and expressive.


yonatanel: yeah… programming is so precise one bit out and it's a catastrophic failure and how many trillion bits are we handling these days?


it’s a miracle of engineering anything works at all


(for me, it’s sheer stubbornness: “I will not be beaten by an inanimate object!” so I must “defeat” the computer 🙂 )


a quixotic quest if ever there was one 🙂


The docstring of s/def indicates that one can provide a symbol instead of a keyword as the name for a spec, but I cannot find any examples of that. What use case is that for?


@aengelberg s/fdef is equivalent to (s/def symbol (s/fspec ...))


same as defn is (def symbol (fn ...)) 🙂


@bfabry: interesting, thanks. So when would one use specs that have been set to a symbol?


well you're implicitly using them anytime you use instrument


explicitly? I dunno. I can't think of a good one off the top of my head, but that doesn't mean there's not


you could use the registered fspec's to spec a function to be passed in as

(s/or :this `this :that `that :the-other `the-other)
I guess. seems a little contrived


as of the 1.9 alphas, macro inputs are checked via spec, so because the spec is named with the same symbol as the macro, the ns macro's inputs are checked with that spec


thanks, that helps a lot


Suppose I have a datatype (or {:foo/name-type :keyword, :foo/name :my-foo} {:foo/name-type :string, :foo/name "my-foo"}). How can I write that in clojure.spec, if s/keys forces me to commit to one possible spec for a given key?


foo/name will need to be an or spec, then you can enforce the dependency using and with a predicate


Is the fact that :a/b/c gives me a keyword with namespace "a" and name "b/c" an implementation detail?


Because I could technically leverage that with :req-un to have different versions of a namespaced key.


I think that is sort of a design decision baked in to spec, a namespaced key should only ever be mapped to the same kind of thing


spec is sort of a global schema for data in your program


so similar to having a sql table with a schema where you say a column has some type, you don't really say sometimes this column has this type, some times it has this other, depending on where the data comes from


I would guess that a symbol with / in its name is undefined in terms of what will happen


"Symbols begin with a non-numeric character and can contain alphanumeric characters and *, +, !, -, _, ', and ? (other characters may be allowed eventually)."


'/' isn't in that list, so I'd say you're off the edge of the map if you use symbols with it in them


Got it, makes sense. In this case I am working with an existing program that has keys not set up with that philosophy, so I'm just trying to figure out if there's any way I can fall back to more verbose but more flexible behavior a la prismatic schema. Sounds like not.


@bfabry: I was referring to keywords, not symbols.


keywords have the same rules as symbols, but can't contain .


there was a discussion about / in keywords, and it comes up over and over again because clojure allows a larger range of inputs than it should in many places


answer is just don't do that


yes, you can make all sorts of symbols and keywords that the documentation doesn't say is permitted, which is very unfortunate


So what you're saying is that I should use the :a/b/c keyword NOW while I can before it becomes officially unusable.


Just kidding. I don't in fact want to watch the world burn.


Is this intentional?

user> (s/explain #{1 2 3} 4)
val: 4 fails predicate: :clojure.spec/unknown
Specifically the "unknown" part. Seems like the predicate should be more informative when it fails.


special case. if you def'd that predicate to the registry you'd get better message


user=> (s/def ::foo #{1 2 3 4})
user=> (s/explain ::foo 5)
val: 5 fails spec: :user/foo predicate: #{1 4 3 2}


user=> (s/explain (s/spec #{1 2 3}) 4)
val: 4 fails predicate: #{1 3 2}


basically, explain is not a macro


spec tries to transparently treat things that could be specs (like sets and predicates) as specs


so those generally work


but there are places where it doesn't, like in the message, there, I suspect its and easy fix if you open an issue


s/explain must be calling whatever part of the spec protocol implements s/form on the set, and the spec protocol has a fallback on object which returns the unknown keyword


there may already be an issue, spec is only out in alphas

Alex Miller (Clojure team)19:11:19

@aengelberg re the unknown in explain - that’s a known bug and will be fixed

Alex Miller (Clojure team)19:11:35

I’ve worked on it a bit but waiting for some feedback from Rich

Alex Miller (Clojure team)19:11:56

I should probably log an actual jira for it so I can just point people to it

Alex Miller (Clojure team)19:11:06

re your prior question, depending on your goal, you can s/def :foo/name with an s/or or you could define different s/keys specs and s/or those

Alex Miller (Clojure team)19:11:17

but the latter seems like it would be papering over the true range of variability in the spec for that attribute

Alex Miller (Clojure team)19:11:44

if your goal is really coercion, then there may be other options (conformers) to consider


any best practices for ns qualifying keywords that come out of a db?


in particular is there a function for adding a namespace to all bare keys in a map


One observation whilst playing with spec is that it seems to be “static” by design, in that it doesn’t seem to encourage or allow you to programmatically build/modify and refine specs. For example one thing I used to do with schema (especially in tests) was define a generic schema for something and then in specific tests where I want to test something more specifically e.g. the presence of a specific test value in the output, I’d simply assoc a new specific value into the schema, and validate against that. Is this a fair point in understanding the pro’s and con’s of spec vs other schema libraries?


(I should say it seems totally fair to me that spec trades off dynamism for something more static and comprehensible)


hard to say


the combinators are different


instead of associng in, you might s/and a new s/keys spec


I think there is a bias in spec towards naming things globally, vs some kind of local names or anonymous things


I guess I'd say, I don't think spec is particularly static, but the bias towards global names can make it feel that way some times. And the bias is just a bias, you can do that kind of stuff, you might just have to venture off the beaten path of what is provided in the box


hiredman: yeah I think you’re right


How can you define mutually recursive specs?


I don't remember having to do anything special.

Alex Miller (Clojure team)23:11:12

Just refer to them by (qualified keyword) name

Alex Miller (Clojure team)23:11:34

They delay evaluation so should just work