Novato no Common Lisp: Macro Pergunta para a definição de pacotes on the Fly
-
07-07-2019 - |
Pergunta
Ainda lutando para entender o que as melhores práticas são com respeito a macros. Eu estou tentando escrever uma macro que define pacotes em tempo real.
(defmacro def-dynamic-package (name)
`(defpackage ,(intern (string-upcase name) "KEYWORD")
(:use :common-lisp)))
Isso funciona bem apenas para expressões como:
(def-dynamic-package "helloworld")
Mas falha miseravelmente para algo como isto:
(defun make-package-from-path (path)
(def-dynamic-package (pathname-name path)))
ou
(defun make-package-from-path (path)
(let ((filename (pathname-path)))
(def-dynamic-package filename)))
Eu entendo como a maioria das macros básicos trabalhar, mas como implementar este me escapa.
Solução
defpackage é uma macro. Como tal, ele é expandido em tempo de compilação, não em tempo de execução. O que você quer é algo que é chamado pelo tempo de execução, a fim de fazer um novo pacote. Portanto, defpackage não pode fazer nada por você.
Felizmente, há também make-package , que fornece defpackage recursos 's como uma função. Usá-lo em vez de defpackage .
Outras dicas
O fracasso é de se esperar aqui, porque uma macro é usada quando o seu argumento não deve ser avaliada.
Na sua primeira make-pacote-de-caminho, o dynamic-pacote def receberá como argumento uma lista que é igual ao valor da seguinte expressão:
(list 'pathname-name 'path)
No seu caso, você só quer uma função:
(defun def-dynamic-package (name)
(defpackage (string-upcase name)
(:use :common-lisp)))
BTW, se você verificar o CLHS , você ver que o primeiro argumento da defpackage não precisa ser um símbolo, mas qualquer corda designador .