This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-09-12
Channels
- # beginners (63)
- # boot (3)
- # braveandtrue (153)
- # cider (19)
- # cljdoc (2)
- # clojure (80)
- # clojure-dev (25)
- # clojure-italy (73)
- # clojure-losangeles (1)
- # clojure-nl (4)
- # clojure-spec (67)
- # clojure-sweden (1)
- # clojure-uk (83)
- # clojurescript (56)
- # clojutre (11)
- # core-logic (37)
- # cursive (18)
- # datomic (14)
- # editors (10)
- # emacs (13)
- # figwheel-main (11)
- # fulcro (62)
- # graphql (11)
- # jobs (3)
- # klipse (1)
- # leiningen (6)
- # off-topic (91)
- # onyx (7)
- # pedestal (3)
- # portkey (5)
- # re-frame (14)
- # reagent (13)
- # remote-jobs (1)
- # shadow-cljs (111)
- # tools-deps (4)
- # yada (10)
Is it possible to write a spec that generates a sequence where each element in the sequence has some relationship to the previous element(s) in the sequence?
As an example, like one that multiplies the last element of a sequence by 2 or 3 (random).
I mean I would like to use test.check
with this generated sequence, so I assume that means using both (I think).
the way I would handle this is to use gen/bind
generate a series of random multipliers (a sequence of random 2s and 3s)
then gen/bind to turn the sequences of multipliers into a sequence of values
or rather, I guess gen/fmap is sufficient here
it’s just apply a function to that sequence
Yeah, so what I was really hoping was to generate the initial (seed) state of my program as the first element in the sequence, and generate the rest of the sequence by constantly looking at the last element in the sequence, determining what actions can be taken at that state, and then picking one of those actions and applying it to said state.
yeah, same idea
start from a gen of a tuple feeding the fmap
(s/gen (s/tuple int? (s/coll-of #{2 3} :max-count 10)))
then gen/fmap a function over that that takes the first element in the tuple and repeatedly applies the multipliers in the second element to produce a sequence
Ok, the only wrinkle I see there is that only a subset of all of the actions are valid for some of the states.
Maybe, I can just make it so that if the action taken is NOT a valid action for that state, it just returns the original state (identity).
if you need to randomly choose an action per state, you will need to move to gen/bind
but I think you could make that work too
Interesting, interesting. I mean I tried to read through the "rose tree" thing for test.check generators. And... well, it looks like it is generating some sort of tree using something like a recursive algorithm. But, yeah, got lost there. 🙂
in that case, I’d probably gen the initial state and the number of actions to gen
yes, but you don’t need to worry about that - the key is just to capture all randomness via generators
test.check will do the rest
this is advanced generating, but it’s where things get interesting
a lot of interesting problems in simulation testing look like this
Really, it is just the fantasy I have of letting spec generate every possible way that my program could run and being like "yep, that one thing encompasses all the test".
You still get a great deal of benefit out of using the normal fdef
and test.check
per function imo, but the idea of actually generating all states of the program would be really cool.
@samedhi @alexmiller this is exactly what the stateful-check library tries to automate, I believe. I haven't used it
@gfredericks Awesome :thumbsup:
Is there some way to specialize a key in s/keys
? Like I have a (s/keys :req [.... ::type])
where type is #{"ORG", "USER"}
, but now I'd like that same spec but where type is limited to `#{"ORG"}
@taylor do you mean custom generator?
no I mean if you wanted to conform/validate a sequence like that, asserting that each element is a multiple of the previous
I was trying to imagine how you might use the spec primitives to do that but I can't imagine how
not as a pred in the coll spec, but you could s/and with a function that verified that
or, maybe you could put that in :kind if you had a seq-of-mults?
pred
@roklenarcic no, but you can s/and it with a more restrictive predicate
It tried to s/merge
it with another keys spec which has key that is more restrictive, with different keyword ns and same name
it kinda works, in that it will check both
there are pros/cons to those approaches wrt conform and gen
ah, haven't thought about that
I think s/and is the most direct way to say it: “I have this map AND it must meet this extra constraint”
s/multi-spec can also be handy for some cases like this but it’s a lot of weight to add if it’s only this
I'll need to check out multi-spec
Using spec-tools
's data-spec solves a couple problems, but sadly data-spec has a bug where they don't name their specs
Spec isn't designed as a data transformation system and when folks ask about doing it, @alexmiller usually pops up and says that's not a good idea 🙂
That said, I think there are some use cases where limited coercion is acceptable. For example, we use spec for API / form input validation so data is mostly strings but we want strings, longs, doubles, Booleans, and sometimes dates out of it. I think that sort of spec is "OK" if you're careful (in particular, think about generation of data using such specs, as well as applicability of the spec elsewhere in your system -- just because you accept strings at the API/form level doesn't mean you want to accept strings elsewhere in your domain model).
What sort of data transformation were you thinking about @lilactown?
i have a general purpose edn format I'd like to use, and then coerce it into the JSON representation for the particular CMS we're using
to be specific, transforming data use conformers in spec is imo not a good idea. using spec as a target for driving transformations is potentially a good idea. I think https://github.com/wilkerlucio/spec-coerce is pretty good.