Новичок в Common Lisp: Макро Вопрос для определения пакетов на лету - PullRequest
5 голосов
/ 11 ноября 2008

Все еще пытается понять, каковы лучшие практики в отношении макросов. Я пытаюсь написать макрос, который определяет пакеты на лету.

(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)))

Я понимаю, как работает большинство основных макросов, но как его реализовать, ускользает от меня.

Ответы [ 2 ]

8 голосов
/ 11 ноября 2008

defpackage - это макрос. Таким образом, он расширяется во время компиляции, а не во время выполнения. То, что вы хотите, это то, что вызывается во время выполнения для создания нового пакета. Поэтому defpackage ничего не может сделать для вас.

К счастью, есть также make-package , который предоставляет функции defpackage как функцию Используйте его вместо defpackage .

0 голосов
/ 11 ноября 2008

Здесь следует ожидать сбоя, потому что макрос используется, когда его аргумент не должен оцениваться.

В вашем первом make-package-from-path def-dynamic-package получит в качестве аргумента список, равный значению следующего выражения:

(list 'pathname-name 'path)

В вашем случае вам нужна только функция:

(defun def-dynamic-package (name)
  (defpackage (string-upcase name)
    (:use :common-lisp)))

Кстати, если вы проверите CLHS , вы увидите, что первый аргумент defpackage не обязательно должен быть символом, но любой строковый указатель .

...