4

很抱歉问了这么一个基本的问题。希望答案不明显的事实主要是由于 clojure.spec 仍然是 alpha 版本(0.1.134)。

如何在此规范错误消息中找到违规代码的文件名和行号?关键是什么:in,sc。价值[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))}
...}

输入时出现此错误lein repl。我对违规行的猜测在这里:

(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 ->]))

因为当我从我在 Clojure 1.8 下运行的目录中复制它时,首先出现了错误消息。此代码在 Clojure 1.8 下工作。

如果我没有这个方便的线索,我想知道如何追踪有问题的文件和行。即使有这个线索,我也不知道该怎么办。我不知道错误是在我的代码、clojure.core/ns 代码还是 clojure.core/ns 中的规范中。还有,In: [2 1]指的是什么?


更新我发现了错误。我上面的猜测是错误的。该错误甚至不在我的代码中!它在 clojure.core.async 中。我使用的是旧版本:0.2.374。我更改为当前版本 0.3.443,并结束了错误消息。显然,在 Clojure 1.9 之前编写的许多代码都利用了ns宏中的一些松懈,比如省略了前面的冒号:require和其他关键字,所以这将是一个常见问题,直到库更新并且依赖项更新以指向更新的库。一个类似的错误出现在popen中(已经修复——这是快速服务!)。

不过,我的问题不是关于这个错误的细节。这是关于一般问题的:如何在不通过像这样的反复试验进行长时间追逐的情况下找到有问题的代码行。

4

1 回答 1

2

当您在ns表单中出错时,您收到的错误消息非常糟糕(比“平均错误”的 Clojure 错误消息更糟糕)。我发现的唯一解决方案是在测试运行之间保持非常有限的更改数量。

我使用的另一种技术是在 Google 中搜索可以复制的正确代码示例。我今天才使用该技术来找到正确的语法:

(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}})

请注意,与require语句不同,关键字命名空间中没有“alpha”,这进一步混淆了事情。我敢让您尝试从在线文档中猜出正确答案:

用法: (check) (check sym-or-syms) (check sym-or-syms opts) 对由 sym-or-syms、符号或符号集合命名的 var 运行规范一致性生成测试。如果未指定 sym-or-syms,请检查所有可检查的变量。

opts 映射包括以下可选键,其中 stc 别名为 clojure.spec.test.check:

::stc/opts 选择通过 test.check/quick-check :gen
映射从规范名称到生成器覆盖

::stc/opts 包括 :num-tests 以及 test.check 记录的键。生成函数 args 时,将生成器覆盖传递给 spec/gen。

如果所有其他方法都失败了,您别无选择,只能使用历史悠久的技术来找到一个可行的超级最小案例然后一次向您的目标添加一个小的更改,直到它失败。我经常发现在一个新的、干净的项目中做这样的实验更容易,lein所以我确信没有未知的问题会混淆这个问题。


PS你总是可以问别人。选择以下一项或多项:

于 2017-10-08T00:42:31.003 回答