2024 年 Clojure 状态调查! 分享您的想法。

欢迎!请参阅 关于 页面以了解更多关于如何使用本网站的信息。

0
Clojure
编辑

我认为在函数中像处理宏一样对传递到函数中的字面代码进行规范会有价值。也许 `fdef` 可以接受一个 `:syntax` 规范作为参数,用于此目的。

有很多我认为这会有用的函数。许多函数将接受以关键字的形式提供参数,这些参数很可能是以字面的形式提供的,因此在读取时对函数调用的使用进行规范是有价值的。

此功能还可以用于其他一些场景,例如对于简单的使用,如 `+`,其中参数通常包含字面数字,这时规范可以在读取时确保不会将关键字或字符串字面作为语法错误传递给它。

实际上,我发现许多 Clojure 函数本身都有特定的语法,如果能用规范在读取时代替宏进行语法规范那就太棒了。

2 个答案

0

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

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

我还有一个实验性项目,可以从spec信息中提取并生成clj-kondo类型注解: http://github.com/clj-kondo/inspector

Malli将做类似的事情,所以任何使用malli schema的函数都可以通过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` spec接收一个额外的`:syntax` spec,它只用于匹配函数调用的语法。这将纯粹是语法的,这就是为什么我经常允许`(s/or symbol? list? ...)`,也许在这里也为符号、形式或字面量提供便利的spec会更好,因为所有函数参数都将遵循此模式。

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

也许我们实际上不需要单独的`:syntax` Spec。可能我们可以使用`:args` spec,但以一种方式,其中所有参数都隐式地用`(s/or symbol? list? arg-spec)`包装。这可能最为方便。这样,`:args` spec就可以这样在读取时应用于验证函数语法(因此使用字面量和参数计数/顺序),就像它在宏中做的那样。

...