Clojure

Spec generator override won't work on multi-spec dispatch key

Details

  • Type: Defect Defect
  • Status: Open Open
  • Priority: Minor Minor
  • Resolution: Unresolved
  • Affects Version/s: Release 1.9
  • Fix Version/s: None
  • Component/s: None
  • Labels:
  • Environment:
    [org.clojure/clojure "1.9.0"]
    [org.clojure/spec.alpha "0.1.143"]
  • Patch:
    Code
  • Approval:
    Triaged

Description

Generator override doesn't work as expected on multi-specs.
Code below illustrates the problem.

(s/def ::obj-type #{:a :b})

(s/def ::base-obj (s/keys :req [::obj-type]))

(defmulti obj-type ::obj-type)
(defmethod obj-type :a [_]
  ::base-obj)
(defmethod obj-type :b [_]
  ::base-obj)

(s/def ::obj (s/multi-spec obj-type ::obj-type))
(gen/sample (s/gen ::obj {::obj-type #(gen/return :a)}))

In the example above the dispatch-fn ::obj-type for the multimethod is given a generator override.
It is expected to return only colls of {::obj-type :a}
Actually it will also return {::obj-type :b}.
That is a generator cannot be used to constrain the set of dispatch-keys to sample from.

Current method:

In the case of a multimethod a generator is constructed for every possible dispatch value.
One is then chosen randomly without paying any attention to overrides for the dispatch-fn(key).

Patched method:

Commit available here
Patched version constructs generators for dispatch values exactly as original.
After that a check is made to see if there exists an override for the dispatch-fn.
If so a gen/bind is done using the override generator.
The bind function generates a value from the override generator.
That value is then used to lookup and return the correct multimethod generator.

Test case

  1. CLJ-2311.patch
    09/Mar/18 9:35 AM
    2 kB
    Andreas Liljeqvist
  2. multi_spec_bug.clj
    12/Jan/18 5:18 AM
    0.8 kB
    Andreas Liljeqvist

Activity

Hide
Andreas Liljeqvist added a comment -

Patch provided for issue.

Show
Andreas Liljeqvist added a comment - Patch provided for issue.
Hide
Alex Miller added a comment -

Can you move the code for the problem into the description and explain the problem and the change?

Show
Alex Miller added a comment - Can you move the code for the problem into the description and explain the problem and the change?
Hide
Andreas Liljeqvist added a comment -

I can't figure out how to edit the description...

description:
In the case of a multimethod a generator is constructed for every possible dispatch value.
One is then choosen randomly without paying any attention to overrides for the dispatch-fn(key).

commit: https://github.com/bonega/spec.alpha/commit/9cb42478b52eac275d496ec29669e2bf4b3e8e1f
My patch hopefully fixes that by checking if there exists an override for the dispatch-fn.
If so a gen/bind is done to the override generator and the result is used to lookup the correct multimethod generator.

Test case: https://pastebin.com/62ZT5Zfc
The test is expected to pass.
Basically I want to generate ::obj with an overriding generator like `(gen/generate (s/gen ::obj {::obj-type #(gen/return :a)}))`.
Expected result should always be `{::obj-type :a}`.
Previously :b was possible as output even though an override was specified.

Show
Andreas Liljeqvist added a comment - I can't figure out how to edit the description... description: In the case of a multimethod a generator is constructed for every possible dispatch value. One is then choosen randomly without paying any attention to overrides for the dispatch-fn(key). commit: https://github.com/bonega/spec.alpha/commit/9cb42478b52eac275d496ec29669e2bf4b3e8e1f My patch hopefully fixes that by checking if there exists an override for the dispatch-fn. If so a gen/bind is done to the override generator and the result is used to lookup the correct multimethod generator. Test case: https://pastebin.com/62ZT5Zfc The test is expected to pass. Basically I want to generate ::obj with an overriding generator like `(gen/generate (s/gen ::obj {::obj-type #(gen/return :a)}))`. Expected result should always be `{::obj-type :a}`. Previously :b was possible as output even though an override was specified.
Hide
Alex Miller added a comment -

I've given you edit right for the ticket so you can make the updates...

Show
Alex Miller added a comment - I've given you edit right for the ticket so you can make the updates...
Hide
Andreas Liljeqvist added a comment -

I have updated the description.
Let me know if anything is unclear.

Show
Andreas Liljeqvist added a comment - I have updated the description. Let me know if anything is unclear.

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated: