在你的想法中,请参与 2024 Clojure 状态调查!

欢迎!请访问关于页面以获取有关如何使用本站的一些更多信息。

0
Clojure
编辑

我认为在函数规范中对传递给函数的文本代码进行匹配,类似于宏的实现将会有价值。可能 fdef 也可以接受一个 :syntax 规范,这将用于此。

我认为有相当多的函数可以看出这一点是有用处的。很多函数将接收选项,例如作为关键词,这些选项很可能是以文本形式提供的,因此在读取时间对于函数调用的使用进行匹配将是宝贵的。

在其他可能有用的情况中,比如对简单的使用例如 +,其中参数经常包含文本数字,规范又可以在读取时应为一种语法错误验证一个关键字或字符串文本不传给它。

实际上,我发现许多 Clojure 函数本身都有特定的函数语法,如果规范能够在读取时间以与宏相同的方式进行语法匹配那就太好了。

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进行相应的lint化。

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` Spec。可能我们可以使用`:args` spec,但以一种方式,其中所有参数都隐式地包裹在`(s/or symbol? list? arg-spec)`中。这可能是最方便的方式。这样,`:args` spec就可以在读取时应用于验证函数语法(从而使用字面量和参数数量/顺序),就像它对宏所做的。

...