【发布时间】:2011-01-10 18:45:44
【问题描述】:
我想在 Elisp 中创建一个如下所示的 DSL:
(install
;; do install
)
(uninstall
;; do uninstall
)
但是,由于 Elisp 有一个全局命名空间,这不是一个好主意。而且给这样的函数加上前缀,实在是太丑了。
(package-install
;; do install
)
(package-uninstall
;; do uninstall
)
所以我认为作为一种折衷方案,所有命令都可以包装在这样的命令调用中:
(commands
(install
;; do install
)
(uninstall
;; do uninstall
)
;; ...
)
但由于我不想在全局命名空间中 install 和 uninstall,我不知何故必须在命令宏中,将所有出现的命令替换为可能例如前缀名称,如下所示:
(defmacro commands (&rest body)
(mapcar
(lambda (exp)
(setcar exp (intern (concat "package-" (symbol-name (car exp)))))
(setcdr exp (list (cons 'progn (cdr exp)))))
body)
`(progn ,@body))
(commands
(install
;; do install
)
(uninstall
;; do uninstall
)
;; ...
)
这似乎是一个 hack。另外,如果有任何嵌套命令,它将不起作用。
有什么好的解决方案或者破解方法吗?
谢谢!
【问题讨论】:
-
YASnipper 在它们的函数前面加上
yas/,所以你得到yas/expand等等。我一点也不觉得那是丑陋的。我采用了我写的 tfs 集成的约定,所以有tfs/checkout、tfs/add等等。在没有正式支持的情况下,这似乎是一种既便宜又简单的名称范围界定方法。 -
只是一个风格注释:我不会像在
command宏的定义中那样使用setcar/setcdr。创建一个新的cons(这甚至可以使代码更干净)。你不知道,如果你的宏扩展器以破坏性的方式任意修改原始代码树,它可能会产生什么影响。