Question

Still struggling to understand what best practices are with respect to macros. I'm attempting to write a macro which defines packages on the fly.

(defmacro def-dynamic-package (name)
  `(defpackage ,(intern (string-upcase name) "KEYWORD")
     (:use :common-lisp)))

This works fine only for expressions such as:

(def-dynamic-package "helloworld")

But fails miserably for something like this:

(defun make-package-from-path (path)
  (def-dynamic-package (pathname-name path)))

or

(defun make-package-from-path (path)
  (let ((filename (pathname-path)))
     (def-dynamic-package filename)))

I understand how most basic macros work but how to implement this one escapes me.

Was it helpful?

Solution

defpackage is a macro. As such, it's expanded at compile-time, not run-time. What you want is something that is called at run-time in order to make a new package. Therefore, defpackage can't do anything for you.

Fortunately, there's also make-package, which provides defpackage's features as a function. Use it instead of defpackage.

OTHER TIPS

Failure is to be expected here, because a macro is used when its argument should not be evaluated.

In your first make-package-from-path, the def-dynamic-package will receive as argument a list that is EQUAL to the value of the following expression:

(list 'pathname-name 'path)

In your case, you only want a function:

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

BTW, if you check the CLHS, you'll see that the first argument of defpackage needn't be a symbol, but any string designator.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top