Giter Site home page Giter Site logo

Comments (4)

miikka avatar miikka commented on June 2, 2024 3

It certainly is surprising behavior. For comparison:

(def spec-a (ds/spec ::spec-a {:x int?}))
(def spec-b (ds/spec ::spec-b {:x nil?}))

(s/valid? spec-a {:x nil}) ;; false

The idea is that if you provide a qualified name for the map key, it is used as-is, and for not-qualified keys the name is generated (example: user$spec-a/x). This is in line with Rich Hickey's and clojure.spec's idea that the same (qualified) map key should always hold the same kind of data.

So it's not an outright bug, but ds/spec silently redefining existing specs seems bad. It should probably throw an exception (maybe there should be an option to allow redefinitions – I don't immediately see an use case, but it would at least allow migration in case any users rely on the existing behavior).

from spec-tools.

arichiardi avatar arichiardi commented on June 2, 2024

Oh I have run into this when trying to override a key for an entity before the following:

(def ^:private crux-entity-w-ranges
  (assoc crux-entity
         :reference-range-set/reference-ranges
         (s/coll-of ::mapper.reference-range/crux-entity)))
(def crux-entity-w-ranges-spec (ds/spec {:name ::crux-entity-w-ranges :spec crux-entity-w-ranges}))

I basically wanted to reuse the same structure for both, but it does not seem to be possible if I understand it right?
The :reference-range-set/reference-ranges always gets overridden if qualified.

What would be a possible workaround (apart from malli 😄) ?

from spec-tools.

arichiardi avatar arichiardi commented on June 2, 2024

I tried the following but for some reason it still does not work (still checking for the :reference-range-set/reference-ranges key)

(def ^:private crux-entity-w-ranges
  (dissoc crux-entity :reference-range-set/reference-ranges))
(def crux-entity-w-ranges-spec (ds/spec {:name ::crux-entity-w-ranges :spec crux-entity-w-ranges}))

It makes sense, being the spec globally defined.

I ended up patching like so:

;; Data Spec follows what spec does here and seems to always
;; override :reference-range-set/reference-ranges.
;;
;; See https://github.com/metosin/spec-tools/issues/252
;;
;; Quite horrible and we should really consider Malli as an alternative.
(s/def ::reference-ranges
  (s/or :uuids (s/coll-of ::mapper.reference-range/id)
        :entities (s/coll-of ::mapper.reference-range/crux-entity)))

from spec-tools.

dehli avatar dehli commented on June 2, 2024

Started looking into this a little and unfortunately I don't think it would be possible due to the fact that spec doesn't support having the same namespace qualified keyword spec'd in more than one way.

For example, given the following specs:

(def spec-a (ds/spec ::spec-a {:a/x int?}))
(def spec-b (ds/spec ::spec-b {:a/x nil?}))

we could auto-generate the following two specs for the above namespace qualified keys.

(s/def ::$spec-a$a/x int?)
(s/def ::$spec-b$a/x nil?)

And then in theory we could write the following specs:

(s/def ::$spec-a (s/keys :req [::$spec-a$a/x]))
(s/def ::$spec-b (s/keys :req [::$spec-b$a/x]))

however there's no way for us to write the above spec so that we're checking a map that contains the :a/x key instead of ::$spec-a$a/x.

I think throwing an error like you had initially suggested would be the best option so that users don't accidentally redefine specs.

If there are other suggestions for how this could be possible I'd be happy to explore them. Thanks!

from spec-tools.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.