Fork me on GitHub
#clojure-spec
<
2016-06-22
>
Oliver George02:06:51

I was expecting s/conform to return fully "conformed" data but it doesn't seem to work like that.

Oliver George03:06:00

=> (s/conform (s/coll-of (s/conformer (fn [x] (println "I am conforming" x) (str x))) []) ["1" 2 :3])
I am conforming 1
I am conforming 2
I am conforming :3
["1" 2 :3]

Oliver George03:06:04

it uses the conformer in order to check the data but returns the un-conformed data. Seems to be "non-recursive"

Oliver George03:06:43

Is that intended behaviour? Perhaps I'm attempting to use it incorrectly - as a data verification & transformation tool.

Alex Miller (Clojure team)03:06:34

The problem here is that coll-of samples its contents and doesn't flow the entire contents

Alex Miller (Clojure team)03:06:53

There are some things in this area changing in next alpha

Oliver George03:06:48

Thanks Alex, I think I see similar behaviour with map-of.

Alex Miller (Clojure team)04:06:44

every and every-kv are new things already in master but not yet released

Alex Miller (Clojure team)04:06:29

One of those sets will conform all args, although I'm not sure which

Oliver George04:06:31

Perfect. Thanks.

akiel11:06:53

Is there a way to spec values which will be conveyed over a channel or returned by a promise?

Alex Miller (Clojure team)11:06:19

ultimately I expect there will be some things provided for core.async

Alex Miller (Clojure team)11:06:09

you could supply a map transducer to an async channel that called s/conform or something like that though

akiel12:06:50

some kind of spec wrapper which takes a spec and validates channel values on the go would be nice

akiel12:06:11

I only like to be sure that nothing speaks at this conceptionally before spec gets final

eggsyntax14:06:18

test.check has a fn (`fmap`) that lets you call an arbitrary fn on the results of a generator. But is there any way to create a generator that just calls an arbitrary fn? I haven't found one. The only solution I've found so far is to do (fmap (fn [_] do-what-I-want) some-arbitrary-gen), but it's pretty ugly to put in a generator and then ignore what it generates.

eggsyntax14:06:04

(I understand that shouldn't be a typical use, but it'd be good to have an escape hatch for cases where you have an existing source of randomness that you don't want to have to duplicate)

akiel14:06:53

@eggsyntax: As you said already, it’s not the typical use to implement the root generator yourself. You have to understand that test.check needs to control the generated values in a way to get shrinking work. So I have no answer to your question only the suggestion: Don’t do this! 🙂

eggsyntax14:06:49

Heh, fair enough.

eggsyntax14:06:25

Although in this case I'm still gonna do it...again, existing (complex) source of domain-specific randomness.

eggsyntax14:06:53

Maybe I'll have to figure out how to make a Rose tree from it...

eggsyntax14:06:19

I realize there's a likely cost in terms of shrinking, though.

eggsyntax19:06:49

@alexmiller: I have, but it looks like that'll only generate a constant value, right? I need something that'll call a fn every time it needs a new one.

angusiguess19:06:02

test.check does have a no-shrink qualifier too I believe.

angusiguess19:06:23

If the value doesn't benefit from shrinking (like uuids for ex)

bostonaholic23:06:16

has anyone come up with a reasonable clojure.spec/def for a database argument?

bostonaholic23:06:27

all I’m using at the moment is ::s/any

bostonaholic23:06:33

(defn get-user [db id] ...)

(s/def ::database ::s/any)

(s/def ::user (s/keys :req [::id ::email]))

(s/fdef get-user
        :args (s/cat :db ::database :id ::id)
        :ret ::user)

bostonaholic23:06:29

but obviously that won’t work with generators

bostonaholic23:06:38

I’m not sure there’s much value here, but interested in hearing what a possible solution might be

eggsyntax23:06:25

@bostonaholic: what should the DB argument look like?

bostonaholic23:06:04

well, it’s a datomic db

eggsyntax23:06:01

Ah, ok, you hadn’t mentioned it was datomic.

bostonaholic23:06:31

that’s why I’m thinking this isn’t a good idea

Oliver George23:06:59

@alexmiller picking up on my question about fully conforming yesterday. I tried every-kv this morning (cljs release) and I see the same behaviour:

Oliver George23:06:04

=> (do
  (s/def ::tree (s/or
                  :branch (s/every-kv keyword? ::tree)
                  :value ::s/any))
  (s/conform ::tree {:A {:B 2}}))

[:branch {:A {:B 2}}]
Was hoping for [:branch {:A [:branch {:B [:value 2]}]}] or similar.

eggsyntax23:06:55

You can certainly check the type using a predicate built from instance?

eggsyntax23:06:37

That might be enough for your needs.

bostonaholic23:06:48

yeah, that’s the only other thing I could think of

eggsyntax23:06:38

That's enough to show it's a legit database...you could also do something like

(s/and #(instance? datomic.db.Db %)
                       (s/keys :req-un [::key1 ::key2]))
with further specs for those keys. (don't have a datomic-using project right in front of me, I'm improvising on the type, and assuming that it's a record)

eggsyntax23:06:24

(which could be dead wrong 🙂 )

bostonaholic23:06:34

you’re right

eggsyntax23:06:21

@bostonaholic: ooh, quite a few keys there, huh? (:id :memidx :indexing :mid-index :index :history :memlog :basisT :nextT :indexBasisT :elements :keys :ids :index-root-id :index-rev :asOfT :sinceT :raw :filt)

bostonaholic23:06:57

heh, yeaahhhhhhhhh

Alex Miller (Clojure team)23:06:38

@olivergeorge: I believe when it is done map-of will be what you want