Re: Help with using spec
Hi Alex, Thanks very much for this, makes sense and has solved my issue. After a trying a few things, it appears that the ArityException was thrown because I would have needed to wrap my regex with s/spec i,e, (s/fdef my-function :args (s/cat :board (s/spec ::board))) So I think this all makes sense now. Thanks again. Jason On 17 October 2016 at 21:02, Alex Millerwrote: > I would back way up to the beginning and reconsider your ::board spec. > Generally for any data where the structures are homogenous, you're probably > better off using one of the collection specs like coll-of (or map-of, > every, every-kv) rather than a regex, which should primarily be used when > you have a sequential structure with syntactic "parts" to it (such as an > arg string or other "dsl" type use case). > > Because s/and flows conformed values you can get the same effect as you > did with &: > > (s/def ::board (s/and (s/coll-of ::row :min-count 1) #(apply = (map count > % > > Your generator seems like it should work. You might also want to constrain > more tightly than pos-int? to keep it from getting out of hand. You could > use something like (s/gen (s/int-in 1 10)) for example. > > > > On Monday, October 17, 2016 at 2:32:20 PM UTC-5, Jason Courcoux wrote: >> >> Hi. >> >> I've been experimenting with clojure spec and a game of life problem, and >> have been trying to spec a rectangular board of unknown size made up of a >> collection of rows, each of which contain an equal number of cells. My >> initial attempt was:- >> >> (def cell? #{0 1}) >> >> (s/def ::row (s/coll-of cell? :min-count 1)) >> >> (s/def ::board (s/& (s/+ ::row) >> #(apply = (map count % >> >> >> This appears to work, but I'm wondering if there is a better way to >> specify the constraint that every row should be the same length? What would >> be the recommended way to achieve this? >> >> Following on from this, I then wanted to generate input boards and >> exercise a function so I tried the following which give me an >> ArityException:- >> >> (s/def ::board (s/with-gen >> (s/& (s/+ ::row) >> #(apply = (map count %))) >> #(gen/bind (s/gen pos-int?) >> (fn [n] >> (s/gen (s/coll-of (s/coll-of cell? :count >> n))) >> >> (s/fdef my-function :args (s/cat :board ::board)) >> >> (defn my-function [board]) >> >> (s/exercise (:args (s/get-spec `my-function)) 1) >> >> => ([([1] [0] [0] [1] [0]) {:board [[1] [0] [0] [1] [0]]}]) >> >> (s/exercise-fn `my-function) >> >> => ArityException Wrong number of args (20) passed to: user/my-function >> >> > This is pretty interesting and the number 20 is pretty suspicious as > that's the max number of args per function - I'm guessing pos-int? is > causing problems there. > > >> >> >> If I try and do something similar without the custom generator such as: >> >> (s/def ::coll (s/coll-of (s/coll-of int? :count 2))) >> >> (s/fdef my-function2 :args (s/cat :board ::coll)) >> >> (defn my-function2 [board]) >> >> (s/exercise (:args (s/get-spec `my-function2)) 1) >> >> => ([(*[*[0 -1] [0 -1] [0 -1]*]*) {:board [[0 -1] [0 -1] [0 -1]]}]) >> >> (s/exercise-fn `my-function2) >> >> This all works as expected. I can see that there is an extra level of >> nesting here though and this must be where the error is coming from, as >> it's applying my-function to the collection rather than using it as a >> single argument - but I'm not sure what is causing this difference. >> >> These look the same in terms of structure: >> >> (gen/sample (s/gen ::coll) 1) >> => ([[-1 -1] [-1 0] [0 -1] [-1 -1] [-1 0] [-1 0]]) >> >> (gen/sample (s/gen ::board) 1) >> => ([[0 1] [1 1] [1 1] [1 1] [1 1] [0 0] [0 1]]) >> >> (s/fdef my-function :args (s/cat :board ::board)) >> >> (s/fdef my-function2 :args (s/cat :board ::coll)) >> >> >> But these don't: >> >> (gen/sample (s/gen (:args (s/get-spec `my-function))) 1) >> => (([1 0] [0 0] [0 1] [0 1] [1 1])) >> (gen/sample (s/gen (:args (s/get-spec `my-function2))) 1) >> => (([[-1 -1] [-1 -1] [0 0] [0 0] [-1 0] [-1 -1] [0 0]])) >> >> >> I'm sure it's something obvious, but I been looking for a couple of hours >> and can't seem to see it - could someone please help point me in the right >> direction. >> >> Thanks in advance. >> >> Jason >> >> >> -- >> Jason Courcoux >> > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails
Re: Help with using spec
I would back way up to the beginning and reconsider your ::board spec. Generally for any data where the structures are homogenous, you're probably better off using one of the collection specs like coll-of (or map-of, every, every-kv) rather than a regex, which should primarily be used when you have a sequential structure with syntactic "parts" to it (such as an arg string or other "dsl" type use case). Because s/and flows conformed values you can get the same effect as you did with &: (s/def ::board (s/and (s/coll-of ::row :min-count 1) #(apply = (map count % Your generator seems like it should work. You might also want to constrain more tightly than pos-int? to keep it from getting out of hand. You could use something like (s/gen (s/int-in 1 10)) for example. On Monday, October 17, 2016 at 2:32:20 PM UTC-5, Jason Courcoux wrote: > > Hi. > > I've been experimenting with clojure spec and a game of life problem, and > have been trying to spec a rectangular board of unknown size made up of a > collection of rows, each of which contain an equal number of cells. My > initial attempt was:- > > (def cell? #{0 1}) > > (s/def ::row (s/coll-of cell? :min-count 1)) > > (s/def ::board (s/& (s/+ ::row) > #(apply = (map count % > > > This appears to work, but I'm wondering if there is a better way to > specify the constraint that every row should be the same length? What would > be the recommended way to achieve this? > > Following on from this, I then wanted to generate input boards and > exercise a function so I tried the following which give me an > ArityException:- > > (s/def ::board (s/with-gen > (s/& (s/+ ::row) > #(apply = (map count %))) > #(gen/bind (s/gen pos-int?) > (fn [n] > (s/gen (s/coll-of (s/coll-of cell? :count > n))) > > (s/fdef my-function :args (s/cat :board ::board)) > > (defn my-function [board]) > > (s/exercise (:args (s/get-spec `my-function)) 1) > > => ([([1] [0] [0] [1] [0]) {:board [[1] [0] [0] [1] [0]]}]) > > (s/exercise-fn `my-function) > > => ArityException Wrong number of args (20) passed to: user/my-function > > This is pretty interesting and the number 20 is pretty suspicious as that's the max number of args per function - I'm guessing pos-int? is causing problems there. > > > If I try and do something similar without the custom generator such as: > > (s/def ::coll (s/coll-of (s/coll-of int? :count 2))) > > (s/fdef my-function2 :args (s/cat :board ::coll)) > > (defn my-function2 [board]) > > (s/exercise (:args (s/get-spec `my-function2)) 1) > > => ([(*[*[0 -1] [0 -1] [0 -1]*]*) {:board [[0 -1] [0 -1] [0 -1]]}]) > > (s/exercise-fn `my-function2) > > This all works as expected. I can see that there is an extra level of > nesting here though and this must be where the error is coming from, as > it's applying my-function to the collection rather than using it as a > single argument - but I'm not sure what is causing this difference. > > These look the same in terms of structure: > > (gen/sample (s/gen ::coll) 1) > => ([[-1 -1] [-1 0] [0 -1] [-1 -1] [-1 0] [-1 0]]) > > (gen/sample (s/gen ::board) 1) > => ([[0 1] [1 1] [1 1] [1 1] [1 1] [0 0] [0 1]]) > > (s/fdef my-function :args (s/cat :board ::board)) > > (s/fdef my-function2 :args (s/cat :board ::coll)) > > > But these don't: > > (gen/sample (s/gen (:args (s/get-spec `my-function))) 1) > => (([1 0] [0 0] [0 1] [0 1] [1 1])) > (gen/sample (s/gen (:args (s/get-spec `my-function2))) 1) > => (([[-1 -1] [-1 -1] [0 0] [0 0] [-1 0] [-1 -1] [0 0]])) > > > I'm sure it's something obvious, but I been looking for a couple of hours > and can't seem to see it - could someone please help point me in the right > direction. > > Thanks in advance. > > Jason > > > -- > Jason Courcoux > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Help with using spec
Hi. I've been experimenting with clojure spec and a game of life problem, and have been trying to spec a rectangular board of unknown size made up of a collection of rows, each of which contain an equal number of cells. My initial attempt was:- (def cell? #{0 1}) (s/def ::row (s/coll-of cell? :min-count 1)) (s/def ::board (s/& (s/+ ::row) #(apply = (map count % This appears to work, but I'm wondering if there is a better way to specify the constraint that every row should be the same length? What would be the recommended way to achieve this? Following on from this, I then wanted to generate input boards and exercise a function so I tried the following which give me an ArityException:- (s/def ::board (s/with-gen (s/& (s/+ ::row) #(apply = (map count %))) #(gen/bind (s/gen pos-int?) (fn [n] (s/gen (s/coll-of (s/coll-of cell? :count n))) (s/fdef my-function :args (s/cat :board ::board)) (defn my-function [board]) (s/exercise (:args (s/get-spec `my-function)) 1) => ([([1] [0] [0] [1] [0]) {:board [[1] [0] [0] [1] [0]]}]) (s/exercise-fn `my-function) => ArityException Wrong number of args (20) passed to: user/my-function If I try and do something similar without the custom generator such as: (s/def ::coll (s/coll-of (s/coll-of int? :count 2))) (s/fdef my-function2 :args (s/cat :board ::coll)) (defn my-function2 [board]) (s/exercise (:args (s/get-spec `my-function2)) 1) => ([(*[*[0 -1] [0 -1] [0 -1]*]*) {:board [[0 -1] [0 -1] [0 -1]]}]) (s/exercise-fn `my-function2) This all works as expected. I can see that there is an extra level of nesting here though and this must be where the error is coming from, as it's applying my-function to the collection rather than using it as a single argument - but I'm not sure what is causing this difference. These look the same in terms of structure: (gen/sample (s/gen ::coll) 1) => ([[-1 -1] [-1 0] [0 -1] [-1 -1] [-1 0] [-1 0]]) (gen/sample (s/gen ::board) 1) => ([[0 1] [1 1] [1 1] [1 1] [1 1] [0 0] [0 1]]) (s/fdef my-function :args (s/cat :board ::board)) (s/fdef my-function2 :args (s/cat :board ::coll)) But these don't: (gen/sample (s/gen (:args (s/get-spec `my-function))) 1) => (([1 0] [0 0] [0 1] [0 1] [1 1])) (gen/sample (s/gen (:args (s/get-spec `my-function2))) 1) => (([[-1 -1] [-1 -1] [0 0] [0 0] [-1 0] [-1 -1] [0 0]])) I'm sure it's something obvious, but I been looking for a couple of hours and can't seem to see it - could someone please help point me in the right direction. Thanks in advance. Jason -- Jason Courcoux -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.