Новичок в Common Lisp:Макрос-вопрос для определения пакетов "на лету"
-
07-07-2019 - |
Вопрос
Все еще пытаюсь понять, каковы наилучшие практики в отношении макросов.Я пытаюсь написать макрос, который определяет пакеты "на лету".
(defmacro def-dynamic-package (name)
`(defpackage ,(intern (string-upcase name) "KEYWORD")
(:use :common-lisp)))
Это прекрасно работает только для таких выражений, как:
(def-dynamic-package "helloworld")
Но с треском проваливается из-за чего-то подобного:
(defun make-package-from-path (path)
(def-dynamic-package (pathname-name path)))
или
(defun make-package-from-path (path)
(let ((filename (pathname-path)))
(def-dynamic-package filename)))
Я понимаю, как работают большинство базовых макросов, но как реализовать этот, от меня ускользает.
Решение
дефакация является макросом.Как таковой, он расширяется во время компиляции, а не во время выполнения.То, что вам нужно, - это то, что вызывается во время выполнения, чтобы создать новый пакет.Следовательно, дефакация ничего не могу для тебя сделать.
К счастью, есть также make-упаковка, который обеспечивает дефакацияфункции как функция.Используйте его вместо дефакация.
Другие советы
Здесь следует ожидать сбоя, потому что макрос используется, когда его аргумент не должен быть вычислен.
В вашем первом make-package-from-path def-dynamic-package получит в качестве аргумента список, РАВНЫЙ значению следующего выражения:
(list 'pathname-name 'path)
В вашем случае вам нужна только функция:
(defun def-dynamic-package (name)
(defpackage (string-upcase name)
(:use :common-lisp)))
Кстати, если вы проверите CLHS, вы увидите , что первый аргумент дефакация не обязательно быть символом, но любой обозначитель строки.