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

+1 vote
in Spec by
As a consequence of the destructuring specs being implemented in terms of `s/keys`, defining a spec for `::keys` or `::strs` is problematic at the moment, because it will conflict with trying to use `::keys` for destructuring:

user=> (require '[clojure.spec :as s])
user=> (s/def ::keys nil?)
user=> (let [{::keys [a]} {::a 1}] a)
ExceptionInfo Call to clojure.core/let did not conform to spec:
In: [0 0] val: #:user{:keys [a]} fails spec: :clojure.core.specs/local-name at: [:args :bindings :binding :sym] predicate: simple-symbol?
In: [0 0 0] val: ([:user/keys [a]]) fails spec: :clojure.core.specs/seq-binding-form at: [:args :bindings :binding :seq] predicate: (cat :elems (* :clojure.core.specs/binding-form) :rest (? (cat :amp #{(quote &)} :form :clojure.core.specs/binding-form)) :as (? (cat :as #{:as} :sym :clojure.core.specs/local-name))),  Extra input
In: [0 0 :user/keys] val: [a] fails spec: :user/keys at: [:args :bindings :binding :map :user/keys] predicate: nil?
:clojure.spec/args  ([#:user{:keys [a]} #:user{:a 1}] a)
  clojure.core/ex-info (core.clj:4725)

This feels like an implementation detail leak.

4 Answers

0 votes

Comment made by: bbloom

I also just ran in to this problem. Just wanted to say that I'd like to see a fix, but I'm not quite sure about the proposed solution. Or, at least, the name "closed?" seems to imply a non-extensible map, when in reality the flag more or less means "not a map that participates in the global keys system", for which I do not have a better name suggestion.

0 votes

Comment made by: alexmiller

The proposed patch is a non-starter. I have some ideas on how to address this, but just haven't gotten around to working on it yet.

0 votes

Comment made by: alexmiller

Removed proposal and patch from the ticket as we will not be going this direction. Captured here for reference:

"The attached patch implements a proposed solution to this issue, by adding a :closed? option to s/keys and using it for the destructuring spec. If s/keys is used with :closed? set to true, conform will only validate declared specs as opposed to the default behaviour of s/keys of validating all namespaced keywords with existing specs.

After this patch, the above example runs fine and usages of s/keys without :closed? set to true will validate against ::keys as per current behaviour.

Patch: close-destructuring-keys-specs.diff"

0 votes
Reference: https://clojure.atlassian.net/browse/CLJ-2074 (reported by bronsa)