Welcome! Please see the About page for a little more info on how this works.

0 votes
in Spec by
Context:

When data fails to conform to a spec, the ":val" of a problem points to the non-conforming data. This has the nice property that the ":val" (for each problem) will exist somewhere within the ":value" (for the entire "explain-data" structure). For example:


(require '[clojure.spec.alpha :as s])

(s/explain-data
 (s/coll-of int?)
 [1 2 :a])
  
;; #:clojure.spec.alpha{:problems ({:path [], :pred int?, :val :a, :via [], :in [2]}), :spec #object[clojure.spec.alpha$every_impl$reify__934 0x1b235c3e "clojure.spec.alpha$every_impl$reify__934@1b235c3e"], :value [1 2 :a]}


This interpretation of ":val" doesn't seem to apply when a function fails to conform to an fspec spec.

Repro:


(require '[clojure.spec.alpha :as s])

(s/explain-data
 (s/coll-of (s/fspec
             :args (s/cat :x int?)))
 [(fn [%] (/ 1 %))])

;; #:clojure.spec.alpha{:problems ({:path [], :pred (apply fn), :val (0), :reason "Divide by zero", :via [], :in [0]}), :spec #object[clojure.spec.alpha$every_impl$reify__934 0x420c3355 "clojure.spec.alpha$every_impl$reify__934@420c3355"], :value [#function[expound.alpha/eval28876/fn--28880]]}


Expected: In order to be consistent with the way "val" normally works, "val" should be the anonymous function. While the function arguments are very useful, perhaps they could be associated with a different key?
Actual: "val" contains the arguments to the function, so it's no longer true that the "val" exists within the "value".

4 Answers

0 votes
by

Comment made by: bbrinck

This also makes the error messages misleading:

`
(s/explain
(s/coll-of (s/fspec

         :args (s/cat :x int?)))

[(fn [%] (/ 1 %))])

;; In: [0] val: (0) fails predicate: (apply fn), Divide by zero
`

because it seems to indicate that the args are failing to conform, whereas the issue is that the function itself is not conforming.

0 votes
by

Comment made by: alexmiller

Please don't set the fix version - core team will do this when it's targeted to a release. This won't be addressed for 1.9.

0 votes
by

Comment made by: bbrinck

Sorry about that - I'll be sure to avoid setting that field in the future.

A little more context: there are cases where the "in" for a problem is tricky to interpret (https://dev.clojure.org/jira/browse/CLJ-2192). In Expound, I have use a heuristic to figure out how the "in" path should work, but that heuristic depends on the "val" existing within the "value". Due to this issue, the heuristic doesn't work, which means I can't reliably report the spec error. See https://github.com/bhb/expound/issues/41

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJ-2258 (reported by bbrinck)
...