clojure-spec

About: http://clojure.org/about/spec Guide: http://clojure.org/guides/spec API: https://clojure.github.io/spec.alpha/clojure.spec.alpha-api.html
Alexis Vincent 2019-12-27T17:15:00.014800Z

why does the last example not work?

(def s-id (s/or :uuid uuid? :string string? :keyword keyword? :num number?))
(gen/generate (s/gen s-id)) ;; => works

(s/def ::id (s/or :uuid uuid? :string string? :keyword keyword? :num number?))
(gen/generate (s/gen ::id)) ;; => works

(s/def ::id s-id)
(gen/generate (s/gen ::id)) ;; => doesn't work

Alexis Vincent 2019-12-27T17:16:04.015500Z

are these not equivalent?

(s/def ::id (s/or :uuid uuid? :string string? :keyword keyword? :num number?))
;; and
(def s-id (s/or :uuid uuid? :string string? :keyword keyword? :num number?))
(s/def ::id s-id)

Alexis Vincent 2019-12-27T17:18:28.015800Z

Does s/def do some macro magic?

Alexis Vincent 2019-12-27T17:18:42.016100Z

This is on the latest spec2 btw

seancorfield 2019-12-27T17:22:09.017800Z

s/def converts the symbolic form to an actual Spec expression and then registers the spec name. So in (s/def ::id s-id) you do not have a symbolic form of a spec. It probably should give an error.

Alexis Vincent 2019-12-27T17:23:49.018500Z

thanks! so would I then rather do (s/def ::id (s/spec s-id)) or something similar?

alexmiller 2019-12-27T17:33:17.019300Z

Use s/register instead of s/def

Alexis Vincent 2019-12-27T17:33:31.019500Z

awesome! thanks!

alexmiller 2019-12-27T17:33:52.020100Z

s/register is a function and takes a spec object

1👌
Alexis Vincent 2019-12-27T17:36:23.021600Z

If I have an s/cat expression but would like to generate/validate vectors not arbitry seq’s, how would I express it?

Alexis Vincent 2019-12-27T17:37:05.022200Z

(s/def :order/pair
  (s/with-gen
    (s/cat :base ::asset :counter ::asset)
    #(vec
      (gen/generate
       (s/gen
        (s/cat :base ::asset :counter ::asset))))))
This worksish. But obviously is not ideal

alexmiller 2019-12-27T17:42:07.023100Z

If you’re on spec 2, you can use the new s/catv

alexmiller 2019-12-27T17:43:06.023700Z

It’s difficult to do easily on spec 1

Alexis Vincent 2019-12-27T17:43:39.023900Z

Perfect, thanks 🙂

seancorfield 2019-12-27T17:55:25.024700Z

@alexmiller Should that (s/def ::id s-id) give an error? Or is it valid but just does something unexpected?

alexmiller 2019-12-27T18:05:51.025300Z

Prob error but I’ll look at it next week

Alexis Vincent 2019-12-27T18:20:03.027400Z

This is probably the same issue as before, but, are these not equiv in spec 2? The first one works nicely, but the second one blows up when generating maps from schemas that contain these keys, but not when generating them directly

(s/def :order/id (s/or :uuid uuid? :string string? :keyword keyword? :num number?))
;; vs 
(s/def ::id (s/or :uuid uuid? :string string? :keyword keyword? :num number?))
(s/def :order/id ::id)

seancorfield 2019-12-27T18:33:20.028Z

@mail024 That should probably work but there are bugs in Spec 2 that affect aliasing of specs like that, I believe.

Alexis Vincent 2019-12-27T20:17:04.029400Z

@seancorfield ok thanks!

Alexis Vincent 2019-12-27T21:25:54.032500Z

If I have a schema with a qualified key I’m trying to override inline, it doesnt seem to want to use my override. It just picks the spec from the registry

(s/union
   (s/schema {:event/type #{:event.type/snapshot}})
   (s/schema
    [:event/nanotime]))
Since event/type already exists in the registry and since (I assume) it is qualified. It picks the registry definition not the one i’m declaring inline

seancorfield 2019-12-27T21:31:33.032800Z

You can only use the inline specs for unqualified keys.

seancorfield 2019-12-27T21:32:11.033600Z

Qualified keys are intended to be globally unique so overriding them doesn't make sense in that context (since their meaning is supposed to be globally fixed).

Alexis Vincent 2019-12-27T21:33:27.034500Z

fine. Although in this case it’s the generator I want to override. Would s/with-gen work for this?

seancorfield 2019-12-27T21:33:48.035Z

Yes, possibly. Depending on exactly what you are trying to do.

Alexis Vincent 2019-12-27T21:34:43.036500Z

I have a set of valid event types. Defined as a spec set. I want to define a particular message. Which is some schema, alongside a specific item from the set

seancorfield 2019-12-27T21:34:47.036700Z

If you want the keys in a hash map to "depend on" the value of a particular key, it sounds like you want multi-specs

seancorfield 2019-12-27T21:35:13.037200Z

If you define this as a multi-spec, it should generate correctly automatically.

Alexis Vincent 2019-12-27T21:35:56.037700Z

Thanks 🙂 Ill check them out.

Alexis Vincent 2019-12-27T21:51:59.037900Z

Perfect thanks. Working well