我想在Elisp中创建一个DSL,如下所示:

(install
 ;; do install
 )

(uninstall
 ;; do uninstall
 )

但是,由于Elisp具有全局 namespace ,所以这不是一个好主意。像这样的函数加上前缀,真是太丑了。
(package-install
 ;; do install
 )

(package-uninstall
 ;; do uninstall
 )

因此,我认为所有命令都可以包装在这样的命令调用中,这是一个折衷方案:
(commands
 (install
  ;; do install
  )

 (uninstall
  ;; do uninstall
  )

 ;; ...
 )

但是由于我不想在全局 namespace 中安装并安装而不是,因此我不得不在命令宏中用所有可能出现的命令替换前缀名称,例如:
(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。另外,如果有任何嵌套命令,它将无法正常工作。

有什么好的解决方案吗?还是要走的路?

谢谢!

最佳答案

在本地定义install和 friend 如何?这不会隐藏标准函数,但是看起来并不像您真正追求的那样。

(defmacro commands (&rest body)
  `(flet ((install (&rest args) (apply 'package-install args))
          (uninstall (&rest args) (apply 'package-uninstall args)))
     ,@body))

当然,您希望自动生成该flet参数列表。您确实需要在某处(可能使用(feature-symbols 'package))列出包元素的列表。

09-04 20:23