6

有没有办法在 Clojure 中将符号标记为已过时?

我可以使用来自 Lein 的类似的东西,效果很好。

https://github.com/technomancy/leiningen/blob/1.x/src/leiningen/core.clj#L13

但是它只在调用函数时发出警告。我真的希望编译器在编译代码时而不是在调用它时选择它。

当然,我不能定义编译器随后会选择的符号,但这剥夺了我提供任何信息的能力,例如为什么或何时弃用该符号。

所有这一切都适用于 DSL,其中术语的弃用和过时将以合理的速度发生。

4

2 回答 2

1

评论中已经有一些关于使用宏的内容,但正如有人指出的那样,这排除了将函数用作 HOF。你可以解决这个问题,尽管治疗方法可能并不比疾病更糟。例如,假设您的功能是

(defn foo* [x y] (+ x y))

然后代替写作

(defmacro foo [x y] (warn) `(foo* x y))
(foo 1 2)
(map foo [5 6] [7 8])

您可以使宏扩展返回一个函数,当然可以像其他任何函数一样使用它:

(defmacro foo [] (warn) `foo*)
((foo) 1 2)
(map (foo) [5 6] [7 8])

可能不值得尴尬,但确实提供了一种在使用已弃用的功能时抱怨的方式,同时仍然保持使用 HOF 的可能性。

于 2012-12-26T06:11:07.397 回答
0

这实际上取决于您的 DSL 是如何设计的。如果你可以设计你的 DSL 使得每个表单都必须包含在一个go或类似的调用中,那么你可以编写这个go宏来做这样的事情:

  1. macroexpand-all(从clojure.walk)到传递的形式
  2. 在上面返回的表单上使用postwalk(来自 clojure.walk),并通过可能查看一些已弃用符号的全局列表来检查遇到的任何符号是否已弃用。您可能需要对resolve符号进行操作以获取符号的命名空间限定名称。
  3. 如果发现任何不推荐使用的符号,则打印消息。
  4. 按原样返回输入表单。

然后,此go宏可用于 DSL 的其他预处理,因为这是执行 DSL 的入口点。

注意:您可能需要提出解决方案,让用户从一个已弃用的符号中为他/她自己的符号使用相同的名称,但同样可能不需要这取决于您的 DSL 设计。

于 2012-12-26T08:56:58.207 回答