Fork me on GitHub
#clojure-spec
<
2016-07-25
>
lvh03:07:34

I guess there’s no way to override that? The issue I’m running into is that merge assumes the key specs it gets are open for extension; so keys-excl merged with anything else fails to produce anything, because the keys-excl part of the spec that checks that the map only contains specific keys will fail on all the keys being added by anything that’s merged in

mike_ananev07:07:42

@alexmiller: last call in my clojure function is java (interop) fn call which returns void. So in clojure if java fn returns void we see nil, if i understand correctly.

xcthulhu12:07:29

@lvh: Instead of merge, have you tried to make an intersection operation?

xcthulhu12:07:14

Sometimes the intersection of two keys-excl won't work either of course, since you have certain mandatory keys.

mpenet13:07:03

"closed" key sets seems like a common request, hopefully Rich reconsiders his choice here. I get that he doesn't want to make it the default, but simply providing a way to spec this can't hurt

Alex Miller (Clojure team)13:07:22

There are no plans to revisit that afaik

Alex Miller (Clojure team)13:07:58

@lvh you might try going down the path of treating your map as a coll-of tuple entries instead (make sure to use :into {})

Alex Miller (Clojure team)13:07:40

Then merge that with s/keys to pick up the attribute checks

mpenet13:07:48

It's super easy to please everybody with a system with "closed" keysets by default (you can just add a k/v spec with any? if you want to "open" the map), but that apparently is out of the question. I personally do not understand the logic here. Never saw anybody complain about the "strictness" of prismatic/Schema for these things for instance.

mpenet13:07:38

then again, I don't consider the openness of records a good thing either

lvh14:07:25

@xcthulhu: I’m not sure I understand. As in, remove keys?

lvh14:07:02

I mean, I guess I could, but that seems very gauche. What would that look like? I have a base spec that everything conforms to, and some stuff that’s specific per type (i.e. multi-spec)

xcthulhu14:07:34

@lvh:Yeah, you would remove keys. If a map-spec isn't open under extension, it may be open under specialization.

xcthulhu14:07:18

So provided that your map-specs s1 and s2 that have the form (keys-excl :opt [...] :opt-un [...]) then you could have

(defn intersection
  [s1 s2]
  (spec/with-gen (spec/and s1 s2)
    #(fmap (fn [[a b]] (select-keys a (keys b)))
           (spec/gen (spec/tuple s1 s2)))))

xcthulhu14:07:40

And you'd have the rule:

(valid? (intersection s1 s2) m)
; if and only if
(and (valid? s1 m) (valid? s2 m))

ghadi16:07:52

@mpenet: search slack history for @richhickey expounding on closed keysets making brittle systems

mpenet17:07:43

It's kind of in the same class as static vs dynamic lang/systems imho: it depends, sometimes exactitude is necessary. My point was that allowing both would do no harm, it would be optional.

mpenet18:07:12

I guess that ship has sailed anyway, and likely not open for debate as usual.

ghadi18:07:31

that's a pessimistic attitude

ghadi18:07:52

it's not open for debate (IMHO) because it's a bad idea, and the core team can justify why

ghadi18:07:08

im guessing no one went back to the original discussion. This comes up often enough that it's probably worth documenting why it's not a good idea

glv20:07:46

That’s a pretty good discussion, and includes a not-too-bad way to accomplish it if you really feel you must.