请在 2024年Clojure调查 分享您的想法!

欢迎!请访问 关于页面 获取更多关于此页面的信息。

0
Spec
编辑

我可以在注册表中使用一个无法解析的符号来定义spec,尽管文档似乎表明这不应该是一个可接受的值。这是安全的吗?它是否会继续正常工作?

s/def 的文档说明它以“命名空间限定的关键字或可解析符号”作为其第一个参数。这比 spec指南 更广泛,其中说,“spec名称始终是完全限定的关键字。”

但最近我将一些spec从关键字更改为符号(完全限定但未绑定)且一切似乎都正常工作,从 s/valid?s/conforms/assert,在 s/keys 等中的定义等等。

这里是一个简化示例

user> (require '[clojure.spec.alpha :as s])
nil
user> (ns-resolve 'com.example 'foo)
Execution error at user/eval30383 (form-init8866507034262802929.clj:53).
No namespace: com.example found
user> (s/def com.example/foo string?)
com.example/foo
user> (s/valid? 'com.example/foo "x")
true
user> (s/valid? 'com.example/foo 42)
false
user> (s/valid? (s/keys :req ['com.example/foo]) {'com.example/foo "x"})
true
user> (ns-resolve 'com.example 'foo)
Execution error at user/eval30389 (form-init8866507034262802929.clj:62).
No namespace: com.example found
user> 

我猜测这是一个实现略超前于文档和指南的例子。或者,也许我是对“可解析符号”的含义有所误解。感谢任何指导或提示!

1 答案

+2

选择
 
最佳答案

注册表旨在保存两种类型的键:关键字(命名规范)和解析为函数规范的符号。因为后者的用途是函数规范,除非符号解析,否则它们实际上无法有效解析(因此有文档)。

然而,我们不会在s/def时验证符号是否可解,事实上我们不想这样做,因为这允许规范在引用它的函数之前或之后定义。

您永远不应直接使用符号调用s/def,如本示例所示(这是允许的,因为s/fdef就是这样在底层实现的)。

...