Subject: Re: symbol in macro From: Erik Naggum <erik@naggum.no> Date: 02 Sep 2002 03:17:54 +0000 Newsgroups: comp.lang.lisp Message-ID: <3239925474372819@naggum.no> * cubicle584@mailandnews.com (Software Scavenger) | So you export COLLECT for the sole purpose of making sure the macro | expansion refers to the same COLLECT as the macro definition? Is that | a better solution than using `(... ,(intern "COLLECT") ...) ? I think I see your point, but let me rephrase it. Is it the better solution to let macros define other local macros and functions with `macrolet´, `flet´, and `labels´ with symbols in the package in which the macro is defined or in the current package at the time of expansion? This is a good question. Common Lisp has clearly made the decision that it is the better solution to this problem to rely on the reader for the package of the symbols than to attempt to control the package at macro-expansion time. There are probably many reasons for this, but the ones I can think of include the fact that the creation of symbols has traditionally been a layered concept and has been taken care of by the reader quite independently from any where the symbols would be used in the system and the rather obvious conclusion from the amount of work involved in circumventing this mechanism in order to make a macro more package-friendly, if that is what this is about. However, what would it take to write macros with a conservative view to packages? Let me test this on an alternative to if just for show (defmacro if (condition then-clause &optional else-clause) `(cl:if ,condition ,(cl:if (and (listp then-clause) (eq (car then-clause) (intern (symbol-name 'then)))) `(progn ,(cdr then-clause)) then-clause) ,(cl:if (and (listp else-clause) (eq (car else-clause) (intern (symbol-name 'else)))) `(progn ,(cdr else-clause)) else-clause))) This is not terribly different from or more difficult than using just the symbols, but it needs to be done manually, or some additional macrology needs to be defined that sort of re-interns the symbol. Perhaps this is what it should be called? (defun re-intern (symbol) "Re-intern the symbol in the current package." (intern (symbol-name symbol) *package*)) Now we can write (defmacro if (condition then-clause &optional else-clause) `(cl:if ,condition ,(cl:if (and (listp then-clause) (eq (car then-clause) (re-intern 'then))) `(progn ,(cdr then-clause)) then) ,(cl:if (and (listp else-clause) (eq (car else-clause) (re-intern 'else))) `(progn ,(cdr else-clause)) else))) which is a little bit less intrusive. I considered a macro with-reinterned but that left the symbols unquoted in the body and that just looked wrong. Suppose we want to write this with `macrolet´, instead, although we now make it possible to use then `then´ and `else´ too many places in the code. It could look like this: (defmacro if (condition then-clause &optional else-clause) `(cl:if ,condition (macrolet ((,(re-intern 'then) (&body forms) `(progn ,@forms))) ,then-clause) (macrolet ((,(re-intern 'else) (&body forms) `(progn ,@forms))) ,else-clause))) If it is felt to be exceptionall important to be able to do this, one might imagine reader-macro support for it, as well: (defmacro if (condition then-clause &optional else-clause) `(cl:if ,condition (macrolet ((#`then (&body forms) `(progn ,@forms))) ,then-clause) (macrolet ((#`else (&body forms) `(progn ,@forms))) ,else-clause))) Is something like this in the vicinity of what you had in mind? -- Erik Naggum, Oslo, Norway Act from reason, and failure makes you rethink and study harder. Act from faith, and failure makes you blame someone and push harder.