Fork me on GitHub
#clojure-spec
<
2017-07-24
>
devth19:07:40

continually bitten by not knowing if instrumentation is on during interactive dev (e.g. turn it on, then redefine a symbol - now it's off) and tests for a given symbol. i think it's on, then find out i had an invalid spec in a lib for weeks because the upstream lib turned on instrumentation and threw an exception. :thinking_face:

caio19:07:50

mutable shared state is the root of all evil 🙂

devth19:07:12

i think i want a single jvm flag to turn it on globally

wilkerlucio19:07:35

@devth a flag would be complicated, if you think about how instrumentation works, it actually overrides your var, much like a monkey patch in Ruby if you are familiar with, so it would have to re-trigger on every def situation. a simpler solution would be to find a way to handle it on your editor, make it automatically call s/instrument on file save or something

devth19:07:11

familiar with how it works and monkey patching. that puts the onus of using this thing correctly on users, and the many tools/editors they use

devth19:07:52

so i'm not satisfied with that solution 😛

devth19:07:53

i kinda like how schema had their own s/defn. that would provide the means to flip a global switch.

devth19:07:11

yes i know i'm free to build my own wrapper / macro / lib thing

devth19:07:33

but first have to answer "should i build my own wrapper marcro lib thing?"

wilkerlucio22:07:45

the main issue on having a global toggle would be that it requires a conditional test overhead, imagine if you have to had this overhead on each function call to check if the parameters should be validated or not

wilkerlucio22:07:08

that can be quite expensive, the way instrumentation works right now adds no overhead at all when you are not using it

wilkerlucio22:07:47

currently can be annoying to use, but editors and other features on top of it can solve this issue, while having the global check maybe not have a way to solve from the user code base

devth23:07:44

with a macro it could be zero cost

tetriscodes19:07:40

Hello, I’m trying to gen some JSON for the Netflix Eureka API and it has @‘s in the keys

tetriscodes19:07:02

(spec/def :port-def/$ int-str-gen)
(def enabled (keyword (symbol "port-def" "enabled")))
(spec/def enabled boolean?)
(spec/def ::port-def (spec/keys :req-un [:port-def/$ :port-def/enabled]))

tetriscodes20:07:17

produces :port {:$ "9", :enabled false},

tetriscodes20:07:42

I’ve been trying

(spec/def :port-def/$ int-str-gen)
(def enabled (keyword (symbol "port-def" "@enabled")))
(spec/def enabled boolean?)
(spec/def ::port-def (spec/keys :req-un [:port-def/$ enabled]))

tetriscodes20:07:23

produces :port {:$ "9"}

moxaj20:07:48

@tetriscodes I think you should use a qualified keyword instead of a symbol for the enabled spec

moxaj20:07:29

oh, you can't, the reader throws

tetriscodes20:07:08

I thought :port-def/@enabled was qualified

moxaj20:07:30

@tetriscodes ugly workaround:

(def enabled (keyword (symbol "port-def" "@enabled")))
(defmacro foo []
  `(s/def ~enabled boolean?))
(foo)

moxaj20:07:44

hopefully you don't have too many references to the enabled spec ^^

tetriscodes20:07:37

still no enabled key

tetriscodes20:07:55

spec/keys takes keys that are registered in the catalog as a spec

avi20:07:44

hi all 👋 anyone happen to know why clojure.spec.gen doesn’t include let, and if there’s an idiomatic approach to doing what clojure.test.check.generators/let does?

tetriscodes20:07:44

How are you using it?

avi20:07:25

(def ^:private gen-datetime
  (tc-gen/let [year (gen/large-integer* {:min 2017 :max 2117}) ; we should be so lucky
               month (gen/large-integer* {:min 1 :max 12})
               day (gen/large-integer* {:min 1 :max 28}) ; damn you February
               hour (gen/large-integer* {:min 0 :max 23})
               minute (gen/large-integer* {:min 0 :max 59})
               second (gen/large-integer* {:min 0 :max 59})]
           (str (string/join "/" [year month day])
                " "
                (string/join ":" [hour minute second]))))

avi20:07:58

hmmm maybe there’s an altogether better approach here… I should probably just generate a unix timestamp integer within a certain range, then use clj-time to convert it into the desired string format…

avi20:07:06

I’m still curious about let though

tetriscodes20:07:26

you could use spec/with-gen to make your clause a regex and then have your generator create the date formatted as a string and then use clojure.spec.gen/sample to generate data.

avi20:07:07

Thanks! Not sure I 100% follow but I’ll try to parse that (mentally) and eventually report back. Thank you!

tetriscodes20:07:32

Looks like you are trying to generate data

tetriscodes20:07:37

So writing the generator can create some random data for you, or the library test.chuck has a string-from-regex function that you can use but it may be harder to get the ranges on your numbers.

avi20:07:55

aha, string-from-regex sounds promising, I didn’t know about that!

avi20:07:02

thank you!

avi20:07:19

oh ah I see

avi20:07:23

very cool

avi20:07:25

will check it out

avi20:07:27

thank you!

tetriscodes20:07:36

https://clojurians.slack.com/archives/C1B1BB2Q3/p1500927450713826 that still gives me errors because they vector needs to look up the keywords

tetriscodes20:07:59

That helps get the spec defined but the lookup of the spec’s keyword return nil

tetriscodes20:07:30

I had heard that in the future spec/keys may take a function, but I don’t see that in the latest alphas

moxaj20:07:02

@tetriscodes well, anywhere you'd use that spec, you'll have to wrap that form in a macro to bypass the reader

moxaj20:07:11

hence my comment

moxaj20:07:21

but i'm sure there are cleaner solutions

tetriscodes20:07:43

But how does the definition of the s/keys vector find that key?

tetriscodes20:07:09

Because I still have to do :port-def/@enabled

tetriscodes20:07:17

which isn’t a valid keyword

moxaj20:07:35

(defmacro bar []
  `(spec/def ::port-def (spec/keys :req-un [:port-def/$ ~enabled])))

(bar)

moxaj20:07:51

maybe you could do some preprocessing with spec/and, afaik conformed values flow through

tetriscodes20:07:59

I should use macros everywhere

moxaj20:07:15

definitely not 🙂 this is last resort

tetriscodes20:07:20

Thanks. Its in one spot, so I’ll keep it hidden.

tetriscodes20:07:50

Yes, i’ve been encouraged to avoid them, so I’m not familiar.

moxaj20:07:31

well, macros in general, but particularly in this case, since this is a 'hack'

avi23:07:26

any chance anyone can see what’s wrong with this?

(s/def ::stream-of-string-rows
  (s/with-gen
    #(instance? InputStream)
    (fn [] (gen/fmap (fn [v] (->> (map (partial string/join ",") v)
                                  (string/join "\n")
                                  .getBytes
                                  io/input-stream))
                     (gen/vector (s/gen ::string-row))))))
I keep getting errors like this when I run stest/check on the namespace this is in:
java.util.concurrent.ExecutionException: clojure.lang.ArityException: Wrong number of args (1) passed to: events/fn--4703
            clojure.lang.ArityException: Wrong number of args (1) passed to: events/fn--4703
Not sure what’s happening, because when I define these specs in the REPL they work just fine with gen/generate

avi23:07:24

ah crap I figured it out… the spec should have been #(instance? % InputStream)

avi23:07:20

or, rather (partial instance? InputStream)