2024 年 Clojure 状态调查中分享您的想法!

欢迎!请参阅关于页面了解有关此功能的一些更多信息。

0
Spec

摘要

1) 给定一个.matmul.f 被延迟调用的函数,例如:(def ls (map map-f (range)))。
2) 还有一个.matmul.varargs-f,是一个可变参数函数。当你将一个 LazySeq 传递给.matmul.varargs-f 时,一些或所有元素将被实现,作为符合的结果。
问题:调用 (apply varargs-f ls) 时,一些无效的对 map-f 的调用可能被忽略。

重现示例

在以下代码中,当(matmul.f)用非 Symbol 类型的参数调用时,预期会抛出异常。然而,对(matmul.f)的 String 类型的调用却通过了。

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

(defn map-f [x]
(println "用类型" (type x) "调用 my-fn")
(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")
`

输出

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

原因

当 varargs-f 的参数作为符合的结果实现时,对 map-f 的某些调用是在 with-instrument-disabled 的作用域内进行的:https://github.com/clojure/spec.alpha/blob/f23ea614b3cb658cff0044a027cacdd76831edcf/src/main/clojure/clojure/spec/test/alpha.clj#L140

背景

在指定 merge-with 时遇到此问题时,一些测试命名空间中的指定的函数不再抛出异常,因为 clojure.test 中的此行与上述描述的 spec 问题类似: https://github.com/clojure/clojure/blob/28efe345d5e995dc152a0286fb0be81443a0d9ac/src/clj/clojure/test.clj#L775

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

4 答案

0
by

评论由:borkdude 提出

CLJ-2443.patch 通过在 with-instrument-disabled 的作用域外匹配 Cons 类型参数来修复此问题。
提供了测试。此补丁符合 speculation(《https://github.com/slipset/speculative》)。

0
by

评论由:borkdude 提出

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

0
by

评论由:borkdude 提出

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

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