请在2024 Clojure 状态调查!中分享您的想法。

欢迎!请查看关于页面以了解该工作的更多信息。

0
Clojure
编辑

我认为让 Spec 以与宏相同的方式将字面代码传入函数是有价值的。也许 fdef 可以接受一个 :syntax 规范,这将用于此。

我认为有许多函数可以用这种方式很有用。很多函数会接受关键字作为选项,这些很可能以字面量形式提供,所以在读取时为函数调用对它们的使用进行合规性检查是有价值的。

其他有用的情况可能包括即使是简单的使用,比如 + 操作,其中参数常常包含字面量数字,在这种情况下,规范可以在读取时验证没有将关键字或字符串字面量作为语法错误传递给它。

实际上,我发现许多 Clojure 函数本身都有特定的函数语法,如果能像宏一样在读取时使用 Spec 对其语法进行合规性检查那就太棒了。

2 答案

0

与此相关,如你所知,clj-kondo 也会使用静态分析进行类似的检查。

有关更多信息: https://github.com/borkdude/clj-kondo/blob/master/doc/types.md

我还有一个实验性的项目,该项目可以从规格信息中提取数据,并输出类似于clj-kondo的注解类型:http://github.com/clj-kondo/inspector

Malli 也会做类似的事情,因此任何使用 malli 的定border caffe 规格信息的函数都可以用 clj-kondo 进行相应的代码检查。

by
我在想 clj-kondo 在这方面走得更远。我只是在想关于阅读时进行语法 Spec 的符合性。它不会包括对其他函数返回类型或其他事物的任何了解。

我设想的是像这样

```
(defn foo [a b & options]
  ...)

(s/fdef foo
  :syntax (s/cat :a (s/or symbol? list? int?)
                  :b (s/or symbol? list? string?)
                  :options (s/cat :one (s/? (s/cat :opt #{:one} :val (s/or symbol? list? boolean?)))
                                  :two (s/? (s/cat :opt #{:two} :val (s/or symbol? list? #{:fast :slow}))))

(foo 10 (get-b) :one true :two :slow)
```

因此,`fdef` 规范还会接受一个额外的 `:syntax` 规范,用于符合函数调用的语法。这将完全是一种语法,这也是为什么我会经常允许 `(s/or symbol? list? ...)`,也许在这里提供一个方便的规范同样不错,用于表示可以是符号、形式或字面的东西,因为所有函数参数都将遵循此模式。

但这样做确实提供了很多价值,并且看起来添加起来相当简单,无需创建任何类型概念以及跟踪程序中的类型。这似乎非常适合 Spec。它只是允许与宏已获得的相同类型的 Spec 语法检查宏对函数也进行同样的检查。所以这里它阻止我传递一个不受支持的选项,防止我在函数接受的选项关键字中出错,防止我向选项传递错误的枚举值等。所以至少它覆盖了所有对字面的使用。
0
by

也许我们甚至不需要一个单独的 :syntax 规范。可能我们可以使用 :args 规范,但以一种所有参数都隐式包裹在 (s/or symbol? list? arg-spec) 中的方式。这可能是最方便的。这样,:args 规范就可以在读取时应用于验证函数语法了(从而验证字面量和参数的数量/顺序),就像它已经应用于宏那样。

...