Новичок в Common Lisp:Макрос-вопрос для определения пакетов "на лету"

StackOverflow https://stackoverflow.com/questions/279696

  •  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, вы увидите , что первый аргумент дефакация не обязательно быть символом, но любой обозначитель строки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top