Reputation: 5030
Sorry to ask such an elementary question. Hopefully the fact that the answer isn't obvious is mostly due to clojure.spec's still being an alpha version (0.1.134).
How do I find the filename and line number of the offending code in this spec error message? And what is the meaning of the :in
key, sc. the value [2 1]
?
#error {
:cause Call to clojure.core/refer-clojure did not conform to spec:
In: [2 1] val: :as fails at: [:args :exclude :op :quoted-spec :spec] predicate: #{:exclude}
In: [2 1] val: :as fails at: [:args :only :op :quoted-spec :spec] predicate: #{:only}
In: [2 1] val: :as fails at: [:args :rename :op :quoted-spec :spec] predicate: #{:rename}
In: [2] val: (quote :as) fails at: [:args :exclude :op :spec] predicate: #{:exclude}
In: [2] val: (quote :as) fails at: [:args :only :op :spec] predicate: #{:only}
In: [2] val: (quote :as) fails at: [:args :rename :op :spec] predicate: #{:rename}
:data #:clojure.spec.alpha{:problems ({:path [:args :exclude :op :spec], :pred #{:exclude}, :val (quote :as), :via [], :in [2]} {:path [:args :exclude :op :quoted-spec :spec], :pred #{:exclude}, :val :as, :via [], :in [2 1]} {:path [:args :only :op :spec], :pred #{:only}, :val (quote :as), :via [], :in [2]} {:path [:args :only :op :quoted-spec :spec], :pred #{:only}, :val :as, :via [], :in [2 1]} {:path [:args :rename :op :spec], :pred #{:rename}, :val (quote :as), :via [], :in [2]} {:path [:args :rename :op :quoted-spec :spec], :pred #{:rename}, :val :as, :via [], :in [2 1]}), :spec #object[clojure.spec.alpha$regex_spec_impl$reify__1188 0x437e951d clojure.spec.alpha$regex_spec_impl$reify__1188@437e951d], :value ((quote :exclude) (quote [reduce into merge map take partition partition-by]) (quote :as) (quote core)), :args ((quote :exclude) (quote [reduce into merge map take partition partition-by]) (quote :as) (quote core))}
...}
I get this error when I enter lein repl
. My guess for the offending line is in here:
(ns fargish.util
(:refer-clojure :exclude [rand rand-int cond])
(:require [better-cond.core :refer [cond]]
[clojure.tools.trace :refer :all]
[clojure.pprint :refer [pprint]]
[clojure.math.numeric-tower :as math]
[clojure.core.async :as async :refer [<! <!! >! >!!]]
[clojure.java.io :as io]
[clojure.edn :as edn]
[popen :refer [popen] :as po]
[cheshire.core :as ch]
[lonocloud.synthread :as ->]))
because the error message first appeared when I copied this over from the directory where I was running under Clojure 1.8. This code worked under Clojure 1.8.
I would like to know how to track down the offending file and line if I didn't have this convenient clue. Even with this clue, I'm not sure what to do about it. I can't tell if the error is in my code, the clojure.core/ns code, or a spec in clojure.core/ns. Also, what does In: [2 1]
refer to?
Update I found the error(s). My guess above was wrong. The error wasn't even in my code! It was in clojure.core.async. I was using an old version: 0.2.374. I changed to the current version, 0.3.443, and that ended the error message. Apparently, a lot of code written before Clojure 1.9 exploits some laxness in the ns
macro, like omitting the colon before :require
and other keywords, so this is going to be a common problem until libraries get updated and dependencies get updated to point to the updated libraries. A similar error was in popen (already fixed—that was fast service!).
My question isn't about the specifics of this error, though. It's about the general problem: how to find the offending line of code without going on a long chase by trial-and-error like this.
Upvotes: 4
Views: 635
Reputation: 29976
When you make mistakes in the ns
form, the error messages you get are notoriously bad (worse than the "average bad" Clojure error messages). The only solution I've found is to keep the number of changes very limited between test runs.
The other technique I've used is to search Google for examples of correct code you can copy. I used that technique just today to find this correct syntax:
(ns xyz
(:require
[clojure.spec.alpha :as sp]
[clojure.spec.gen.alpha :as gen]
[clojure.spec.test.alpha :as stest] ))
(stest/check `i/truthy? {:clojure.spec.test.check/opts {:num-tests 99}})
Note that, unlike the require
statement, there is no "alpha" in the keyword namespace, further confusing things. I dare you to try to guess the correct answer from the online docs:
Usage: (check) (check sym-or-syms) (check sym-or-syms opts) Run generative tests for spec conformance on vars named by sym-or-syms, a symbol or collection of symbols. If sym-or-syms is not specified, check all checkable vars.
The opts map includes the following optional keys, where stc aliases clojure.spec.test.check:
::stc/opts opts to flow through test.check/quick-check :gen
map from spec names to generator overridesThe ::stc/opts include :num-tests in addition to the keys documented by test.check. Generator overrides are passed to spec/gen when generating function args.
If all else fails, you have no choice but to use the time-honored technique of finding a super minimal case that does work, then add one small change at a time toward your goal until it fails. I often find it easier to do such experiments in a new, clean lein
project so I am sure there are no unknown problems confusing the issue.
P.S. You can always ask someone. Choose one or more of:
Upvotes: 2