请在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的defn及其模式信息的函数都可以使用clj-kondo进行相应的代码质量控制。

by
我认为clj-kondo在某些方面更进一步。我只是在想语法规范在读取时的实现。这不会包括其他函数返回类型或其他知识。

我想象的是

```
(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规范将能够在读取时应用来验证函数语法(因此使用字面量和参数数量/顺序),就像它对宏所做的那样。

...