Welcome! Please see the About page for a little more info on how this works.

0 votes
in Spec by

While speccing a library I'm working on I tripped on a bheavior of s/unform in combination with s/? which I find odd:

(require '[clojure.core.specs.alpha :as cs])

(def binding-form '[a b :as c])

(def x (s/conform ::cs/seq-binding-form binding-form))
;; x => {:forms [[:local-symbol a] [:local-symbol b]], :as-form {:as :as, :as-sym c}}

(s/unform ::cs/seq-binding-form x) 
;; => (a b (:as c))

(s/valid? ::cs/seq-binding-form (s/unform ::cs/seq-binding-form x))
;; => false

Is this intended behavior? On intuition, I was expecting first unforming would produce the original form and also that the result of unform would validate (using the same spec).

1 Answer

0 votes
selected by
Best answer

There are probably a couple things here. Regex forms parse sequential colls (importantly lists and vectors) but have no way to retain the original collection type and unform to the proper one. This is a generic problem and there are no easy solutions to it (if you consider all the aspects of conform, unform, and gen). We don't have plans to address in spec 1. In spec 2, we now have support for this with s/catv and s/cats which are type-specific variants.

With respect to the (:as c), I think that is a known bug with trailing ? conforming, but it would take me a while to find the link.

Ah yes, there is a bug report: https://ask.clojure.org/index.php/2418/nesting-cat-inside-causes-unform-to-return-nested-result?show=2418#q2418.

I didn't see that. That answers my question.

As for catv, catc -- good to know. I can already see how they'd be useful for macros/dsl situations.