我可以在运行时 fdef 这个,然后在调用 [...]
不,因为instrument
需要一个符号,解析它的 var,然后用一个包装原始函数的新函数替换它——这就是验证输入参数的工作完成的地方。在您的示例中,您将无法访问f
函数的“原始”符号,并且匿名函数不会解析为 var。
你可以指定高阶函数,所以你可以a
这样指定:
(defn a [f] (f (rand-int)))
(s/fdef a :args (s/cat :f (s/fspec :args (s/cat :x number?))))
(st/instrument `a)
(a inc) ;; => 2
(a str) ;; => "1"
(a (fn [x] (assoc x :foo 'bar))) ;; spec error b/c fn doesn't conform
但是......请注意,任何传递f
给检测的函数a
都将使用随机输入多次调用!这就是规范如何确定函数是否符合要求。
(a #(doto % prn inc))
-1
-0.75
...
=> 0.18977464236944408
显然,您不希望将其与副作用或昂贵的功能一起使用。我只推荐instrument
用于测试/开发。你也可以s/assert
在你的函数中使用,但这仍然会调用f
多次。
(s/def ::f (s/fspec :args (s/cat :x number?)))
(defn a [f]
(s/assert ::f f)
(f (rand)))
(s/check-asserts true)
从哲学的角度来看,这是明智的还是有意义的?
这实际上取决于您的程序的性质以及作为f
.