Как создать DSL в Elisp - PullRequest
       28

Как создать DSL в Elisp

6 голосов
/ 10 января 2011

Я хочу создать DSL в Elisp, который будет выглядеть примерно так:

(install
 ;; do install
 )

(uninstall
 ;; do uninstall
 )

Однако, поскольку у Elisp есть глобальное пространство имен, это не очень хорошая идея. И добавление префиксов к таким функциям чертовски уродливо.

(package-install
 ;; do install
 )

(package-uninstall
 ;; do uninstall
 )

Поэтому я подумал, что в качестве компромисса все команды могут быть заключены в вызов команды, подобный этому:

(commands
 (install
  ;; do install
  )

 (uninstall
  ;; do 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
  )

 ;; ...
 )

Это похоже на такой взлом. Кроме того, он не будет работать, если есть какие-либо вложенные команды.

Есть ли какое-то хорошее решение для этого или есть способ взломать?

Спасибо!

1 Ответ

8 голосов
/ 11 января 2011

Как насчет определения локально install и друзей? Это не скроет стандартные функции, но не похоже, что это то, что вам действительно нужно.

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

Конечно, вы захотите сгенерировать этот список flet аргументов автоматически. Вам нужен где-то список элементов вашего пакета, возможно, с использованием (feature-symbols 'package).

...