Fork me on GitHub
#clojure-spec
<
2016-06-07
>
Alex Miller (Clojure team)02:06:17

@wilkerlucio: in addition to the new namespaced support in CLJ-1910 and CLJ-1919 we are considering changes related to aliasing of non-existent namespaces too

wilkerlucio02:06:19

@alexmiller: cool, that would be nice, specially for cljs where I can't do the trick mentioned by @hiredman

Alex Miller (Clojure team)02:06:52

I did some recon on it a few weeks ago and we talked about it briefly again today

wilkerlucio02:06:36

I'm happy to hear that this is being considered, I think with clojure.spec the usage of fully namespaced keywords is going to have a great increase in usage

jcf08:06:21

Found some clojure.spec benchmarks over on Reddit: http://muhuk.github.io/validation-benchmark/ N.B. I haven't independently verified any of the work.

slipset08:06:25

playing with specs and tests in Clojurescript I get this error:

slipset08:06:31

actual: #error {:message "Call to [object Object] did not conform to spec

slipset08:06:56

The error is probably correct, but the message leaves something to be desired.

slipset08:06:51

Having said that, specs are awesome!

mishadoff11:06:01

Hi, could you help me understand clojure.spec Here is the little snippet:

(s/def ::name string?)
(s/def ::specific-name #{"John" "Jack"})
(s/def ::age (s/and integer? #(<= 0 % 100)))
(s/def ::person (s/keys :req-un [::name ::age]))
(s/explain ::person {:name "John" :age 10})
Is there a way to validate that map contains specific key like :name, but value should be matched against another spec, ::specific-name?

slipset11:06:19

(s/def ::person (s/and (s/keys :req-un [::name ::age]) #(#{“John” “Jack”} (:name %))))

slipset11:06:12

not answering your question, but should work.

mishadoff11:06:53

yes, but would be good to use already defined spec ::specific-name instead of copying its implementation

slipset11:06:22

Don't know your code, but you could (def specific-names #{...}) and use that var in the specs

mishadoff11:06:58

I can, but that not a spec anymore

Alex Miller (Clojure team)12:06:27

you can do (s/def ::name ::specific-name) to just alias an existing one

Alex Miller (Clojure team)12:06:50

spec will "chase" registered names like that

Alex Miller (Clojure team)12:06:09

or you could define a predicate that is reused for multiple specs

bronsa14:06:30

looks like spec might need some performance tuning http://muhuk.github.io/validation-benchmark/

Alex Miller (Clojure team)14:06:06

I don't think that test is very good, but that may also be true. will be looking at it today

seancorfield14:06:40

The use case for clojure.spec is different to Schema tho', right?

seancorfield14:06:15

You might have conform in several places for destructuring and some calls to valid? but you're not going to have everything instrumented in production code.

seancorfield14:06:56

Whereas folks do have Schema enabled in production don't they? Hence the focus on performance there.

gfredericks14:06:11

schema aims to be used similarly though

seancorfield14:06:35

Ah, so not in production code then?

gfredericks14:06:41

when you decorate functions with schemas they don't run by default

gfredericks14:06:53

and similar to spec you can turn them all on

gfredericks14:06:04

and you can call them explicitly to validate in/out in production

gfredericks14:06:27

so maybe they focus on performance primarily for that last case?

Alex Miller (Clojure team)14:06:23

we still want spec to have good performance, even when not used in production :)

bronsa15:06:31

@seancorfield: we disable schema in prod, performance hit is way too much

wilkerlucio15:06:53

@mishadoff: like alexmiller said, you can create a new one, if you still need that key on the current namespace, make up a new namespace, eg: (s/def :other-ns.anything/name ::specific-name) and then (s/keys :req-un [:other-ns.anything/name])

mishadoff15:06:18

@wilkerlucio: thanks, for now I’ve decided to use same names for keys and specs

wilkerlucio15:06:23

@mishadoff: cool, that is the preferred way I believe 🙂

mishadoff15:06:33

@wilkerlucio: yes, but sometimes you have maps with unqualified keys from third-party libs

wilkerlucio15:06:48

that's true, maybe with the clojure.spec people will start using more fully qualified keywords from now one, and possibly with specs already coming from the library itself, will be awesome 🙂

gfredericks15:06:11

is :opt in s/keys just for documentation purposes?

gfredericks15:06:29

I can't figure out how else it affects anything

angusiguess16:06:20

@gfredericks: does it work with generators?

gfredericks16:06:51

oh that's probably true

Alex Miller (Clojure team)16:06:05

also, the long-awaited seqable? :)

andrewhr17:06:01

Also, a nice bonus to see an abstraction for Inst 🙂

seancorfield17:06:47

And Alpha 5 is coming… when? 😸

gfredericks17:06:57

alexmiller: oh boy this inst generator

Alex Miller (Clojure team)17:06:26

@seancorfield: winding its way through the tubes

gfredericks17:06:04

TIL that java.util.Date does weird things with negative years

Alex Miller (Clojure team)17:06:25

probably better to use something like inst-in with that :)

gfredericks17:06:31

coming up with reasonable generators in a lot of cases is difficult :/

gfredericks17:06:52

reasonable defaults I mean

gfredericks17:06:09

strings are my best example of that

Alex Miller (Clojure team)17:06:34

here's a bunch of stuff that in no way resembles reality

gfredericks17:06:51

a uniform distribution over unicode characters would give you 99% unprintable things

Alex Miller (Clojure team)17:06:32

notably for spec is the new unform which lets you conform ... backwards

Alex Miller (Clojure team)17:06:05

also in addition to the vast quantity of new predicates in core, there are now specs for long, double, and instant ranges in spec

Alex Miller (Clojure team)17:06:15

and everything gens yay

seancorfield17:06:41

That’s an awesome new release! Thank you (to everyone involved)!

brabster18:06:06

hey folks, I have a question on map-of in spec that I'd appreciate some help with

brabster18:06:32

hopefully this is a good forum, even if it turns out to just be me being dumb!

brabster18:06:13

if I use s/or in the value spec in a map-of, I lose the qualifier I get when I use it on its own

brabster18:06:07

eg. as per docs (s/def ::thing (s/or :name string? :id integer?)) conforms eg. (s/conform ::thing "bob") to [:name "bob"]

brabster18:06:33

but... (s/def ::map-of-kw-to-thing (s/map-of keyword? ::thing)) doesn't behave the same was under conform

brabster18:06:21

(s/conform ::map-of-kw-to-thing {:foo "bob"}) gives {:foo "bob"}, not {:foo [:name "bob"]} as I was expecting

brabster18:06:26

Am I missing something? I expected ::thing to behave the same way regardless of where it was used

brabster18:06:07

oh sorry I see a message in the history that I missed from @alexmiller: Rich said above "currently conform doesn't flow into coll-of, so the value is never conformed, only checked" which I think is likely related to this - sorry!

brabster18:06:31

is there somewhere I can go to see whether this is planned or to ask for it?

gfredericks18:06:45

queue the warnings from all your favorite libraries that clojure.core/boolean? is being replaced by their local copy

Alex Miller (Clojure team)18:06:07

hopefully all benign if the work we did in 1.7 was successful :)

gfredericks18:06:42

what sort of work?

hiredman18:06:12

isn't http://dev.clojure.org/jira/browse/CLJ-1591 still open? I didn't accidentally re-open it did I?

Alex Miller (Clojure team)18:06:01

it's open but it's very narrow in scope iirc - only when defining a new fn of the same name in terms of the old function of the same name, right?

Alex Miller (Clojure team)18:06:34

the general case of just overlapping the name was resolved afaik

Alex Miller (Clojure team)18:06:31

prior issues came up when we added "update"

bronsa18:06:48

yeah, I don't actually think that's a bug

Alex Miller (Clojure team)18:06:50

we have since added other things that were in general use without issue (although I can't remember an example now)

bronsa18:06:19

the fact that def declares the var at analysis time is the only way to write recursive functions with defn

hiredman18:06:39

mmm, I guess I am note sure what version of clojure the guy was running when I w as helping him debug this

Alex Miller (Clojure team)18:06:44

@hiredman: I'm not sure if your final example in the comments is actually the same thing or not, not sure?

bronsa18:06:56

FWIW I couldn't reproduce that example

gfredericks18:06:33

should it be possible to write a function that verifies that none of the keyword-references used in any specs have typos?

gfredericks18:06:56

using keywords instead of vars makes the whole thing feel a lot more typo-sensitive

hiredman18:06:27

yeah, I didn't look at the history to see the current state of the bug, just spent a while trying to figure out why this guys defmulti was resulting in an unbound var, and after way too long I remember that bug, and he said changing the name of his function fixed it, but that is kind of loose, who knows what is happening on the other end of irc

gfredericks18:06:29

by "typos" I mean a keyword that is supposed to refer to a spec but no spec has been registered

Alex Miller (Clojure team)18:06:09

as long as it's registered by the time you use it, it's fine

gfredericks18:06:19

right, so I mean "never registered"

Alex Miller (Clojure team)18:06:27

well never is a long time

gfredericks18:06:57

I could have a test in a codebase that looks at this for example

gfredericks18:06:10

so it would have the responsibility to ensure that all pertinent code is loaded already

pheuter18:06:43

So I’m trying to play around with the new clojure.spec generators, and I keep getting this error: Var clojure.test.check.generators/large-integer is not on the classpath. I definitely have test.check as a dep and i can access various vars under the clojure.test.check.generators namespace, but large-integer isn’t one of them.

gfredericks18:06:03

pheuter: did you add test.check magically later?

gfredericks18:06:11

that's when I get that error

pheuter18:06:14

no, we had it as a dep for a while

gfredericks18:06:25

pheuter: is it an older version? large-integer is new

Alex Miller (Clojure team)18:06:34

are you using test.check 0.9.0 ?

pheuter18:06:39

yeah, 0.9.0

Alex Miller (Clojure team)18:06:50

do you have an older version also on the classpath?

pheuter18:06:52

let me clear deps and try to re fetch

gfredericks18:06:43

yeah do tree ↑ and look for conflicts

gfredericks18:06:54

(at the top of the output)

pheuter18:06:52

good call, will take a look and make some exclusions, thanks!

Alex Miller (Clojure team)18:06:18

@brabster: I asked Rich, he said the point of that was that conform samples (does not check every value) for perf reasons and that is unlikely to change. we might make the docs better around it though

brabster18:06:41

@alexmiller: thanks for the info, would suggest mentioning it with an example in the docs as that's not the behaviour I'd expect from map-of - working around it at the moment but would have been a nice multi-method dispatch off the conformed inputs, looks ugly in comparison now. Will share when pushed up to github, maybe I'm just misusing the functionality!

Alex Miller (Clojure team)18:06:33

I making some updates to the guide for alpha5 right now - I'll try to add a note about that

brabster18:06:20

btw spec is great imho - really neat and well thought through after a few hours of using it

gfredericks19:06:41

alexmiller: the thing that makes me uneasy is when I have to type a fully qualified keyword referencing a spec

gfredericks19:06:55

but where it's actually defined elsewhere using ::

gfredericks19:06:13

or regardless actually

gfredericks19:06:37

with var namespaces the compiler will catch renamings that were only partially done

gfredericks19:06:47

with specs it just looks like something isn't defined yet

pheuter19:06:54

any ideas on how to use generators, possibly custom, to generate Datomic facts? More specifically, I’d like to generate legitimate temp ids, but it’s not clear to me how to express that as a predicate.

gfredericks19:06:34

temp ids are a custom datomic type aren't they?

pheuter19:06:44

a thought is to use a set predicate that’s populated with a bunch of tempids

gfredericks19:06:44

so the predicate would be #(instance? ThatType %)

gfredericks20:06:19

what's the API to create a tmp id? it's a 0-arg function and it returns a unique object each time?

pheuter20:06:24

even simpler, they can be verified as longs! the problem is being able to actually transact them against a test db

pheuter20:06:32

(tempid part)

gfredericks20:06:51

that can't be right...

gfredericks20:06:04

(tempid part) returns a long?

pheuter20:06:31

well not exactly, it returns a :db/id reader value, but you can pull out an :idx long from it

pheuter20:06:50

the problem is getting the generate to generate values in sequential order

gfredericks20:06:01

why does that matter?

pheuter20:06:34

perhaps that part doesn’t matter, that’s just my interpretation of the error I get: db.error/not-a-partition Entity id -1000441 is not in a valid partition

pheuter20:06:42

where -1000441 is a sample temp id

gfredericks20:06:53

are you passing a valid partition to tempid when you call it?

pheuter20:06:19

so how would i call it?

gfredericks20:06:24

you just generate a random long and construct the thing that way rather than calling tempid?

pheuter20:06:01

right, since -1 < n < -100000 is reserved for tempids in the user partition

gfredericks20:06:23

but -1000441 is out of range, does that mean you're accidentally generating out of range numbers?

pheuter20:06:36

sorry, -1000000 is the actual bound

gfredericks20:06:45

still out of range

pheuter20:06:50

you’re right, let me double check

pheuter20:06:05

i’ll feel very silly if that’s the case 😕

gfredericks20:06:41

feeling silly is what programming is all about

pheuter20:06:21

:db.error/not-a-partition Entity id -3427 is not in a valid partition ¯\(ツ)

pheuter20:06:16

ah, it may be how i’m transacting that value, since it expects it in a #db/id reader value

pheuter20:06:24

at least when using the map form

zane20:06:36

For anyone following along, the approach we're gonna try is using clojure.test.check.generators/fmap in conjunction with datomic.api/tempid and clojure.test.check.generators/choose.

gfredericks20:06:58

zane: I assume you are also pheuter; now that I think about it I suspect you'll have to be careful about uniqueness?

gfredericks20:06:26

you can use gen/vector-distinct to get a collection of distinct things

pheuter20:06:29

that was my follow-up ☺️

pheuter20:06:33

oh awesome

zane20:06:42

Good observation!

zane20:06:05

Yes, @pheuter and I are colleagues.

pheuter20:06:27

Hm, looks like gen/vector-distinct is not one of the lazy combinators in clojure.spec.gen

gfredericks20:06:14

you can use it directly from clojure.test.check.generators/vector-distinct

gfredericks20:06:33

wrap it in a function if you have to

pheuter20:06:38

yeah, makes sense