clojure-spec

István Karaszi 2024-08-15T12:35:02.816599Z

Spec overrides and aliases I ran into a counter-intuitive issue. Do I understand it correctly that overriding Clojure spec generators using the clojure.spec.alpha/gen overrides keyword isn’t working with aliases specs?

(ns raszi.spec-overrides
  (:require
   [clojure.spec.alpha :as s]
   [clojure.test.check.generators :as gen]))

(def spec-test (s/with-gen string?
                 #(gen/elements #{"foo" "bar" "foobar"})))

(s/def ::test spec-test)

(s/def ::alias spec-test)

(s/def ::other-alias ::test)

(s/def ::map (s/keys :req-un [::test
                              ::alias
                              ::other-alias]))

(comment
  (gen/generate (s/gen ::test))
  (gen/generate (s/gen ::map))
  (gen/generate (s/gen ::map {::test #(gen/elements #{"FOO" "BAR" "FOOBAR"})})))
I would not expect the ::other-alias spec to be overridden by the overrides attribute.

Michael Banks 2024-08-16T07:50:29.821709Z

This is a known issue: https://clojure.atlassian.net/browse/CLJ-2079

Michael Banks 2024-08-16T07:54:15.103699Z

The workaround I use is to s/def the aliased specs by wrapping the aliased keyword in s/spec, as described in this comment: https://clojure.atlassian.net/browse/CLJ-2079?focusedCommentId=47742

Michael Banks 2024-08-16T07:54:20.950949Z

(s/def ::test (s/spec spec-test))

(gen/generate (s/gen ::map {::test #(gen/elements #{"FOO" "BAR" "FOOBAR"})}))
=> {:test "FOO", :alias "foobar", :other-alias "FOO"}

István Karaszi 2024-08-16T07:56:22.319879Z

I see, thank you for the explanation! I am glad that I got the intentions right and this is an actual issue.

👍 1
István Karaszi 2024-08-16T07:57:26.911689Z

I refactored the code to have the definitions with def-s and the usages with s/def. I guess we can revert the change after this gets fixed.

István Karaszi 2024-08-16T07:57:50.758699Z

If ever, since it is almost a 5 years old issue.

István Karaszi 2024-08-16T08:03:48.065189Z

I guess your suggestion would be:

(s/def ::other-alias (s/spec ::test))

👍 1
István Karaszi 2024-08-16T08:04:12.132709Z

And that seems to be working

István Karaszi 2024-08-15T13:09:19.762609Z

I’ve created this small repro case here: https://github.com/raszi/spec-overrides

István Karaszi 2024-08-15T13:19:27.728579Z

Is this a bug or I actually need to define this re-usable specs using def instead of s/def?

István Karaszi 2024-08-15T14:02:47.330899Z

By doing that the code gets much-much more complicated and other features won’t be supported. 😞

István Karaszi 2024-08-15T18:13:36.542839Z

The worst part here, is that you cannot add an override on the aliased spec name only on the original.