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.

Foi útil?

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 .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top