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

Thanks in advance.


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
For more options, visit this group at
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.

Reply via email to