Fork me on GitHub
#clojure-spec
<
2016-10-07
>
richiardiandrea02:10:39

Hello folks! I know how to spec a map with keys which I don't care the values of: (s/map-of #{:mid :seq} any?) thanks to Alex, but is there a way standard pred to say "any non-nil value" or I must create my own predicate?

richiardiandrea02:10:23

I tried (complement nil?) but then the generator fails

richiardiandrea02:10:43

oh right, let me try

bfabry02:10:01

boot.user=> (s/def ::some some?)
:boot.user/some
boot.user=> (s/exercise ::some)
([{} {}] [{} {}] [(()) (())] [{([[]]) ([])} {([[]]) ([])}] [(-1/2 false) (-1/2 false)] [{{{{{} (-1.5)} ([\=])} []} [{}]} {{{{{} (-1.5)} ([\=])} []} [{}]}] [([:N4oa:*I+-:0:+c8_68:!!-6L]) ([:N4oa:*I+-:0:+c8_68:!!-6L])] [[[([true])]] [[([true])]]] [{} {}] [[()] [()]])
boot.user=>

richiardiandrea02:10:23

yes it looks like that's what I was looking for thanks a lot @bfabry !

seancorfield03:10:05

Looks like some? always generates a collection tho’?

bfabry03:10:04

HUH, that's weird

seancorfield03:10:36

@richiardiandrea what about (s/and any? (complement nil?)) ? That generates regular values that aren’t nil…

boot.user=> (s/exercise (s/and any? (complement nil?)))
([{} {}] [[] []] [[] []] [([false]) ([false])] [[()] [()]] [[] []] [{[[:Q5B+B:-vS7!+_2a:14s+?:Wd:?:E3+cY7:7q9n_V:+T*_] [L?lQDc.poz2z._rRq+9*Le._?.o.Pq!San9?!.uP36/y?+-i_]] {[] {}}} {[[:Q5B+B:-vS7!+_2a:14s+?:Wd:?:E3+cY7:7q9n_V:+T*_] [L?lQDc.poz2z._rRq+9*Le._?.o.Pq!San9?!.uP36/y?+-i_]] {[] {}}}] [{[] ()} {[] ()}] [[:AE+4CW!863.Rt_??z4!.ob*6.*M.J*+7!.?Wpz.RH?.k+L-L?-2_8.Dz_5E3zaY.!2GNEsM/N51M0Sn7 6 5] [:AE+4CW!863.Rt_??z4!.ob*6.*M.J*+7!.?Wpz.RH?.k+L-L?-2_8.Dz_5E3zaY.!2GNEsM/N51M0Sn7 6 5]] [[{[3 \s] [true], (s) (1/6)} {() (:?tLe9B2-66t.--s6+?8E*.*GVek-7!Y.++5BT3TQ6.x0Al3z.*7sAkrq8.*h9.a+P+.qz6?6?/KT-4!m+_4D -8), {\t v-Y+u+D+vk-.K?XwW-8?1?.+!529+.DaEb.erp7.hl?+??ma+t.-ZiN+y+.VC63aicOOe7.!226W+RFO.e1*??7/-q*.} {-5/3 \?}}] [{[3 \s] [true], (s) (1/6)} {() (:?tLe9B2-66t.--s6+?8E*.*GVek-7!Y.++5BT3TQ6.x0Al3z.*7sAkrq8.*h9.a+P+.qz6?6?/KT-4!m+_4D -8), {\t v-Y+u+D+vk-.K?XwW-8?1?.+!529+.DaEb.erp7.hl?+??ma+t.-ZiN+y+.VC63aicOOe7.!226W+RFO.e1*??7/-q*.} {-5/3 \?}}]])

seancorfield03:10:21

Hmm, looking at those, most seem to be collections too…?

seancorfield03:10:05

Ah, I think it’s down to how any? generates stuff...

bfabry03:10:18

there's no reason some? should be only collections, and I think that behaviour might be common

seancorfield03:10:42

Looks like any? generates nil or a collection…

boot.user=> (->> (s/exercise any? 100) (map second) (remove coll?))
(nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)

bfabry03:10:10

yeah seems like whatever any-printable is always generates a coll

bfabry03:10:21

I can't be bothered digging but that seems like not-incorrect-but-pretty-undesirable

seancorfield03:10:31

10,000 iterations don’t produce anything that isn’t nil or a collection:

boot.user=> (->> (s/exercise any? 10000) (map second) (remove coll?) (remove nil?))
()

seancorfield03:10:50

(dang, I love that you can do stuff like that so easily in the REPL!)

bfabry03:10:51

seems like the behaviour is inherited from clojure.test.check.generators/any-printable

bfabry03:10:28

yuuup

boot.user=> (remove coll? (remove nil? (repeatedly 1000 #(clojure.test.check.generators/generate clojure.test.check.generators/any-printable))))
()

seancorfield03:10:53

That probably needs … enhancing ...

richiardiandrea04:10:28

For generating maps only I was thinking of using an s/and but for a first approximation of this spec some? is perfect

richiardiandrea04:10:39

That is good investigation though

prepor07:10:15

Hello. ring-spec had just released. Imagine that library was named not "ring", but "com.stuartsierra.ring". For example, https://gist.github.com/prepor/c9a3ac1c5746146671b55631a543a6e4#file-spec-clj-L107. There are a lot of noise, aren't it?

robert-stuttaford07:10:16

i’ve never understood reverse domain name packages

robert-stuttaford07:10:37

i get the rationale, but it almost never pans out in practice. company names suffice, i find

misha07:10:51

@prepor

(require '[clojure.spec :as s])
(create-ns 'com.this.looks.really.inconvenient)
(alias 'inco 'com.this.looks.really.inconvenient)

(s/def ::inco/bar int?)
=> :com.this.looks.really.inconvenient/bar

(s/valid? ::inco/bar 1)
=> true

(s/valid? :com.this.looks.really.inconvenient/bar 1)
=> true

prepor07:10:13

> i’ve never understood reverse domain name packages this is the only way to guarantee name clashes absence

prepor07:10:57

@misha nice. will it work with aot?

prepor07:10:33

yep. i think dynamic ns juggling is controversial way...

borkdude10:10:00

I’m amazed spec can parse the last case:

(s/def ::rhs (s/cat :lo (s/? symbol?)
                    :r (s/? (s/alt :rsh (s/cat :op #(= % 'RSHIFT)
                                               :ro int?)
                                   :or (s/cat :op #(= % 'OR)
                                              :ro symbol?)
                                   :not (s/cat :op #(= % 'NOT)
                                               :ro symbol?)
                                   ))))

(s/conform ::rhs '[bn RSHIFT 2])
(s/conform ::rhs '[cj OR cp])
(s/conform ::rhs '[lx])
(s/conform ::rhs '[NOT ax])
I expected this not to work because NOT is also a symbol and that none other alt matches the rest

borkdude11:10:02

Is there a conform variant that throws like s/assert but returns the conformed value?

Alex Miller (Clojure team)12:10:08

No but it's easy to make one

Alex Miller (Clojure team)12:10:53

@seancorfield: if you filed a ticket on that any? some? generator business I would take a look at it. I keep forgetting to do so

lvh14:10:40

@borkdude btw, consider #{‘RSHIFT}

lvh14:10:50

@borkdude It’s shorter, generally considered more idiomatic, and spec can inspect it

borkdude14:10:09

@lvh my current spec:

(s/def ::val (s/alt :name symbol? :value int?))
(s/def ::binary-operator #(#{'LSHIFT 'RSHIFT 'AND 'OR} %))
(s/def ::binary-expression (s/cat
                            :left-operand ::val
                            :operator ::binary-operator
                            :right-operand ::val))
(s/def ::not (s/cat :not #(= % 'NOT) :operand ::val))
(s/def ::lhs (s/alt :simple-value ::val
                    :binary-expression
                    ::binary-expression
                    :not ::not))
(s/def ::rhs symbol?)
(s/def ::expr (s/cat :lhs ::lhs :arrow #(= % '->) :rhs ::rhs))

lvh14:10:25

that works too

lvh14:10:31

still gotta fix the #{’NOT} if you want generation to work though

lvh14:10:51

also: arrow

borkdude14:10:57

oh wow, I didn’t even think of generation

lvh14:10:59

borkdude It’s pretty cool. I’m currently generating specs for swagger from the swagger json-schema definition, which I then use the generate swagger instances, from which I then generate instances of that swagger schema, which I then validate against the original swagger

borkdude14:10:57

what reads better, '#{LSHIFT RSHIFT AND OR} or quotes before all symbols?

lvh14:10:36

I dunno; I’d go with quotes before syms

borkdude14:10:50

It works. How do I get s/cat to generate vectors instead of whatever it generates now?

borkdude14:10:53

How do I get a generator that only generates lower case alphabetic strings?

nwjsmith14:10:45

(gen/not-empty
  (gen/fmap
    (fn [s] (str/replace s #"[A-Z0-9]" ""))
    gen/string-alphanumeric))

nwjsmith14:10:21

that's a really naive generator, but it'll get you there

borkdude15:10:03

Thanks! I needed symbols of one or two character, so I got this now:

(s/with-gen symbol?
                  #(gen/fmap (fn [[i j]]
                               (symbol (string/lower-case (str i j))))
                             (gen/tuple (gen/char-alpha) (gen/char-alpha))))

borkdude15:10:28

how do I get s/exercise to generate vectors instead of seqs for s/cat?

nwjsmith15:10:05

Should work with :kind, no?

(s/exercise (s/coll-of (s/cat :a nat-int? :b string?) :kind vector?))

nwjsmith15:10:34

Otherwise, you might want to check out s/tuple

bfabry16:10:08

@seancorfield @alexmiller it actually seems like there's already a ticket on test.check http://dev.clojure.org/jira/browse/TCHECK-111

seancorfield16:10:07

Thanks @bfabry — cross-linked

jrheard21:10:10

ha, hadn’t seen ffirst before, thx for the tip

jrheard21:10:32

hadn’t seen advent of code either, will have to take a look