Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decode can may fail to unform valid specs #119

Open
brokebroke opened this issue May 24, 2018 · 5 comments
Open

Decode can may fail to unform valid specs #119

brokebroke opened this issue May 24, 2018 · 5 comments

Comments

@brokebroke
Copy link

I have a case where I want to use select-spec to narrow a map to a subset described by a multi-spec. The multi-spec is dispatched on an item in the larger collection but would be stripped from the final map. This worked fine in previous releases where select-spec was based on conform (and as a workaround I'm passing the strip-extra-keys-transformer to conform, but I suspect there's an issue with decode

@ikitommi
Copy link
Member

Thanks for the report. Could you provide an example?

@brokebroke
Copy link
Author

Sure, little contrived but my case boils down to something like this:

(spec/def :test/type #{:a})
(spec/def :test/a number?)

(defmulti blob :type)
(defmethod blob :a [_]
  (st/spec (spec/keys :req-un [:test/a])))

(spec/def :test/blob
  (st/spec (spec/multi-spec blob :type)))


;; OK, returns {:a 1}
(st/conform :test/blob {:type :a :a 1} st/strip-extra-keys-transformer)

;; ERROR - CompilerException java.lang.IllegalStateException: No method of: rdp.api.core/blob for dispatch value: ,
(st/select-spec :test/blob {:type :a :a 1})

@ikitommi
Copy link
Member

select-spec does both s/confom and s/unform to effectively return the original value with the extra . The latter fails as the :type key has been removed by the st/strip-extra-keys-transformer. The spec error is not very helpful.

If you change the multi-spec into:

(defmethod blob :a [_]
  (st/spec (spec/keys :req-un [:test/a :test/type])))

it works. Without unform, the transformation is only partial:

(spec/def :test/a (spec/or :int int? :string string?))

;; not good:
(st/conform :test/blob {:type :a :a 1} st/strip-extra-keys-transformer)
; {:type :a, :a [:int 1]}

;; good
(st/select-spec :test/blob {:type :a :a 1})
; {:type :a, :a 1}

hope this helps.

@brokebroke
Copy link
Author

brokebroke commented Jun 25, 2018 via email

@ikitommi
Copy link
Member

I understand, but not sure is there anything we can do for this. https://dev.clojure.org/jira/browse/CLJ-2251 would help as we could just say "coerce" instead of conform + unform. Alex just said that some deep-walking might apper to clojure.spec later-later.

While waiting - if there is a way to ask from a multi-spec what spec it will dispatch for this given data, we could unform against that spec directly, not for the multispec itself. Don't have time now to try that, but would be a welcome addition to the lib.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants