While it doesn't use spec, you can do this using the validate-map-keys
helper function in the Tupelo library <https://github.com/cloojure/tupelo>.
It verify that a map does not contain any keys other than those you
specify.  The unit test shows it in action:

(ns tst.demo.core
  (:use demo.core tupelo.test )
  (:require
    [tupelo.core :as t] ))
(t/refer-tupelo)

(dotest
  (let [map-ab   {:a 1 :b 2}
        map-abc  {:a 1 :b 2 :c 3}]
    (is= map-ab  (validate-map-keys map-ab [:a :b]))
    (is= map-ab  (validate-map-keys map-ab [:a :b :x]))
    (is= map-ab  (validate-map-keys map-ab #{:a :b}))
    (is= map-ab  (validate-map-keys map-ab #{:a :b :x}))
    (is= map-abc (validate-map-keys map-abc [:a :b :c :x]))

    (is (thrown? IllegalArgumentException (validate-map-keys map-ab [:a])))
    (is (thrown? IllegalArgumentException (validate-map-keys map-ab [:b])))
    (is (thrown? IllegalArgumentException (validate-map-keys map-ab [:a
:x])))
    (is (thrown? IllegalArgumentException (validate-map-keys map-abc [:a
:b])))
    (is (thrown? IllegalArgumentException (validate-map-keys map-abc [:a :c
:x])))))


The API docs are hosted on Github Pages, but it seems to be down at the
moment.  You can find some older API docs (May 2017) on CrossClj:
https://crossclj.info/doc/tupelo/0.9.1/index.html

Alan





On Tue, Oct 3, 2017 at 2:37 PM, Didier <didi...@gmail.com> wrote:

> I'm loving Spec as an FYI, and I'll use it even if it stays as is, even in
> its alpha state it is a great tool. I also highly value the Clojure core
> value to avoid breakage, as the cost to enterprise of every migration is
> very high.
>
> I'm just wanting to give more data points to the Core team that I hope
> would be taken into consideration in the decisions of where to put the line
> on what Spec provides and doesn't.
>
> In my case, Spec has already not gone where my code base has. I'm sure
> there's use cases out there where a closed map spec would have been
> problematic, so I'm glad spec has an open map spec, but I've never had this
> problem, and I've failed to see anyone describe it to me where I felt the
> problem was real. What I do know is that I've experienced the problem of an
> open map spec that others have clearly described in this thread. When I
> need to validate for security that no extra keys were added to my maps, and
> when I want to be sure, for correctness, that my instrumentation is not
> accidentally not asserting my input because of a missing key spec, or if I
> want to be reminded that I forgot to update the spec when I extended the
> map to have additional keys, then clojure.spec falls short.
>
> I wouldn't ask of this to be taken into account by the core spec team, if
> it was easy to extend Spec to support this, but from what I could tell from
> the source, it is non trivial for me to add my own strict s/keys, and it
> doesn't seem possible to easily extend s/keys itself with more features.
> Especially if I want all the features of s/keys, except with strict key
> spec validation.
>
> I trust the core team to have good judgement, as they've shown to have
> with much of Clojure till date, but I think this is valuable data points
> for them to discuss and decide what's best. This was also part of a real
> enterprise project, that took 4 months with 5 engineers to develop. We're
> using it in production, so this is not feedback out of a toy project, or
> just experimentation.
>
> Maybe there's a better way to solve this problem then a strict spec, maybe
> we need a strict s/validate?, or some other more powerful and flexible
> construct. And maybe there are easy to extend spec for my needs, then I'd
> love to learn about those.
>
> Anyways, for the purpose of gathering data points about this use case. It
> currently seems like Me, Yury, Leon, Puzzler, and Tommi have all faced this
> issue. I've fixed it by doing my own validation on top of spec. So I only
> use spec as a data description language, and not as a validation tool. I
> use s/describe to get the keys, and then I resolve the specs, and assert
> that no more keys are on the map then what I got from s/describe. The
> downside is that I can't use instrumentation, assert, validate?, etc. So
> its hard to guarantee that the spec is always validated as my data should.
> The spec data description language is not powerful enough to be able to
> model invariants such as a closed set of keys, or keys which must have
> associated specs, unless I implement that predicate spec myself, which I
> couldn't figure out how to do.
>
> Since spec is still alpha, I think this is a great time to bring up these
> issues.
>
>
> On Tuesday, 3 October 2017 13:29:40 UTC-7, Tommi Reiman wrote:
>>
>> Open Specs seem like a good idea.
>>
>> In real life, we need to close our Data at system borders.
>>
>> With Java, there is Jackson, which fails by default on extra keys. The
>> Schema, the models are closed by default. JSON Schemas can be closed.
>>
>> Saying "use normal clojure" on top of Spec mean double-validation, which
>> is both error-prone and boilerplate.
>>
>> Open/Closed is a great principle.
>>
>> Spec should be just more Open to allow people (or 3rd party libs) to
>> extend it to support "close my (open) specs" at runtime = coercion.
>>
>> If Runtime Transformations stay out of scope, It would be good to have a
>> guide on how to write Spec + (beautiful) clojure transformations for
>> web/ring apps. There might be tricks we just haven't thought of.
>>
>> cheers,
>>
>> Tommi
>>
>> tiistai 3. lokakuuta 2017 20.57.34 UTC+3 Alex Miller kirjoitti:
>>>
>>>
>>>
>>> On Tuesday, October 3, 2017 at 12:25:40 PM UTC-5, Didier wrote:
>>>>
>>>> | Spec-tools (https://github.com/metosin/spec-tools) has some tools
>>>> for this: the spec visitor (walking over all core specs, e.g. to collect
>>>> all registered specs) and map-conformers: fail-on-extra-keys and
>>>> strip-extra-keys.
>>>>
>>>> I understand the core team wanting to take a minimal approach to spec,
>>>> and that open is easier to restrict later.
>>>>
>>>
>>> It's not about easier, it's about possible. Open grows, closed breaks.
>>>
>>>
>>>> But I worry that already in alpha state, spec is unpractical for many
>>>> people as is
>>>>
>>>
>>> This is demonstrably false. Many people are using it and happy with it
>>> now.
>>>
>>>
>>>> , and Orchestra and Spec-tools are already needed supplement.
>>>>
>>>> For instrumentation, it's no big deal, but for specs I think it is.
>>>> Having a canonical set of specs accross Clojure shops is a way to form a
>>>> common language. If I start having my custom map specs, and so does
>>>> everyone, I'd be tempted to say something core is missing. Strict map specs
>>>> which also vallidates each key has a registerer spec I think is a glaring
>>>> omission.
>>>>
>>>
>>> I'm not sure how to say this other than that we are playing a longer
>>> game than you, looking out into the future to other potential functionality
>>> and where code bases are likely to go over time.
>>>
>>> We have already seen a number of cases where strict map specs broke
>>> during evolution both inside and outside Cognitect projects as people added
>>> keys. Again, nothing prevents you from both validating your spec AND
>>> applying whatever additional validation you wish to perform. But if you put
>>> the strict check into the spec, you have poured concrete on the spec and it
>>> is dead.
>>>
>>>
>>>> Having used spec in one of my design, I've had to justify already to 6
>>>> people, some being senior security engineers, why the validation allows for
>>>> open keys.
>>>>
>>>
>>> Those other people are right - you should check that if it's important.
>>> But it doesn't have to be part of the spec. Specs should say what must be
>>> true (open), not what MUSTN'T be true (closed). This is in some ways
>>> another variant of the open/closed principle (the O in SOLID).
>>>
>>>
>>>> Other team members were just confused as to why that was, and the only
>>>> argument I had was that Rich doesn't like to break APIs :p.
>>>>
>>>
>>> This is an exceptionally good argument. Why would you dismiss it?
>>>
>>>
>>>> But I've had to add validation on top to pass security audit.
>>>>
>>>
>>> Good!
>>>
>>>
>>>> So I think while not breaking APIs when incrementally adding specs to
>>>> legacy code is a good use case, there's the security and safety use case
>>>> which seems to be shared by a large swat of Clijurist, and I think spec is
>>>> in need of a core support for it.
>>>>
>>>
>>> No, it doesn't! Spec doesn't have to do everything. We've got this whole
>>> beautiful language to use.
>>>
>>>
>> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to