请在2024年Clojure状态调查!

欢迎!请参阅关于页面以获取更多关于本站如何工作的信息。

0
Spec

摘要

1) 给定名为{{map-f}}的可测量函数,该函数被延迟调用,例如(def ls (map map-f (range)))
2) 还有一个名为{{varargs-f}}的可变参数函数。当您将LazySeq传递给{{varargs-f}}时,一些或所有元素都会在符合规范时变为实际行动。
3) 问题:在调用{{(apply varargs-f ls)}}时,一些对{{map-f}}的无效调用可能会未被发现。

重现示例

在以下代码中,{{map-f}}预期在用除Symbol以外的其他类型调用时会抛出异常。然而,用String调用{{map-f}}时,会悄悄地通过。

`
(ns repro
(:require
[clojure.spec.alpha :as s]
[clojure.spec.test.alpha :as stest]))

(defn map-f [x]
(println "用类型调用my-fn" (type x))
(println (deref #'clojure.spec.test.alpha/instrument-enabled))
{x 1})

(s/fdef map-f :args (s/cat :x symbol?))

(defn varargs-f [& maps]
true)

(s/fdef varargs-f :args (s/cat :maps (s/* map?)))

(defn repro [& args]
(apply varargs-f (map map-f args)))

(stest/instrument)

(repro 'foo 'bar "baz")
`

输出

调用my-fn的类型clojure.lang.Symbol true 调用my-fn的类型clojure.lang.Symbol true 调用my-fn的类型java.lang.String ;; <-- nil

原因

当{{varargs-f}}的参数在契合规范后变为实际行动时,一些调用{{map-fn}}的操作在{{with-instrument-disabled}}的作用域内进行:https://github.com/clojure/spec.alpha/blob/f23ea614b3cb658cff0044a027cacdd76831edcf/src/main/clojure/clojure/spec/test/alpha.clj#L140

背景

我遇到这个问题时正在规范化{{merge-with}}。某些测试命名空间中的规范函数不再抛出异常,因为clojure.test中的这一行与上述规范的描述有相似的问题:https://github.com/clojure/clojure/blob/28efe345d5e995dc152a0286fb0be81443a0d9ac/src/clj/clojure/test.clj#L775

CLJ-2443.patch包含了一个修复,但我意识到它可能还不是完美无缺的。因此,我提供了一个只包含单元测试的CLJ-2443-test.patch,该单元测试可用于测试替代解决方案。

4 答案

0

评论由:borkdude发表

CLJ-2443.patch通过将Cons类型参数符合到with-instrument-disabled作用域之外来解决这个问题。
提供了测试。该补丁适用于speculative(https://github.com/slipset/speculative)。

0

评论由:borkdude发表

CLJ-2443-test只包含测试,不包含修复本身。

0

评论由:borkdude发表

使用CLJ-2443-test.patch更新了描述。

0
参考: https://clojure.atlassian.net/browse/CLJ-2443(由borkdude报告)
...