Fork me on GitHub
#clojure-spec
<
2018-08-12
>
ackerleytng03:08:20

@seancorfield I have an example here: https://pastebin.com/Kuat3MPV . That's what i'm doing now, but is there a better way of "namespacing" specs?

seancorfield04:08:25

@ackerleytng OK... and what's the question again? That seems OK to me on the face of it...

ackerleytng04:08:40

ah ok. I just thought there might be a better way of namespacing all of that

lilactown15:08:41

so I have this spec:

(s/def ::projection
  (s/* (s/alt :key keyword?
              :sym symbol?
              :projection ::projection)))
and when I try and run valid?, I get StackOverflowError clojure.spec.alpha/deriv (alpha.clj:1526)

lilactown15:08:59

(s/valid? ::projection [:a :b])

taylor15:08:38

I’m not sure if you’re intending to validate nested collections, but you can do this:

(s/def ::projection
  (s/* (s/alt :key keyword?
              :sym symbol?
              :projection (s/spec ::projection))))

taylor16:08:19

I should mention this only compiles when ::projection has already been defined

taylor15:08:55

(s/valid? ::projection [:a :b 'c])
=> true
(s/valid? ::projection [:a :b 'c "x"])
=> false

lilactown15:08:10

😄 okay awesome. yes, I am intending to validated nested collections

taylor15:08:52

(s/valid? ::projection [:a :b [:c ['d]]]) => true

lilactown15:08:26

what’s the difference between writing :projection ::projection and :projection (s/spec ::projection)?

taylor15:08:59

by default all the regex-type specs “flatten” themselves when nested

taylor15:08:21

wrapping a regex-type spec in s/spec prevents that flattening, so you can use them to describe nested sequences of things

lilactown16:08:13

I don’t understand what you mean by flattening

lilactown16:08:13

or why something “flattening” would cause a stackoverflow

taylor17:08:56

the stack overflow is just because of how spec is implemented, if you have a certain form of nested/recursive regex specs it recurses infinitely trying to evaluate it

taylor16:08:53

@lilactown FWIW you can also define your spec using s/or instead of s/alt, and then you don’t need the s/spec call to prevent the regex flattening:

(s/def ::projection
  (s/* (s/or :key keyword? :sym symbol? :projection ::projection)))

👍 4
taylor16:08:59

by “flattening” I mean that when you nest the regex-type specs, by default they merge/compose/combine/maybe-a-better-word to describe a single sequence

taylor16:08:00

(s/conform
  (s/+ (s/alt :n number? :s string?))
  [1 "2" 3])
=> [[:n 1] [:s "2"] [:n 3]]

taylor16:08:13

(s/conform
  (s/+ (s/alt :n (s/+ number?) :s (s/+ string?)))
  [1 "2" 3])
=> [[:n [1]] [:s ["2"]] [:n [3]]]

taylor16:08:43

but what if you wanted to use regex specs to describe nested sequences? the “flattening” behavior wouldn’t allow it, so you could use s/spec to avoid it:

(s/conform
  (s/+ (s/alt :n (s/spec (s/+ number?)) :s (s/spec (s/+ string?))))
  [[1 2 3] ["1 2 3"]])
=> [[:n [1 2 3]] [:s ["1 2 3"]]]