Prev: Comparing Lisp to Python, what you consider more important:speed or macros.
Next: Rephrasing an English statement into questions.
From: Jonathan Braud on 3 May 2010 17:48 Hello everyone, I'm trying to write a version of defstruct that shadows the name of the structure and exports the constructor and the slot accessors. The macro I wrote macroexpands into what I expect it to, for instance * (macroexpand-1 '(defstruct-shadow-export lambda slot)) (PROGN (SHADOW 'LAMBDA) (DEFSTRUCT LAMBDA SLOT) (EXPORT 'MAKE-LAMBDA) (EXPORT 'LAMBDA-SLOT)) but during the evaluation, I get an error saying: "[The] lock on package COMMON-LISP [was] violated when defining LAMBDA as a structure". If after getting the error, I try to define the structure again, it works as expected. It's as if the shadowing actually occured after the evaluation of the progn. If any of you has an idea why this happens, and/or knows a way around the problem... Thanks in advance.
From: Tim Bradshaw on 3 May 2010 18:19 On 2010-05-03 22:48:19 +0100, Jonathan Braud said: > > (PROGN > (SHADOW 'LAMBDA) > (DEFSTRUCT LAMBDA SLOT) > (EXPORT 'MAKE-LAMBDA) > (EXPORT 'LAMBDA-SLOT)) > Think about read time compared with evaluation time
From: Pascal J. Bourguignon on 3 May 2010 18:56 Jonathan Braud <jonathan.braud.NOSPAMTHANKYOUVERYMUCH+usenet(a)gmail.com> writes: > Hello everyone, > > I'm trying to write a version of defstruct that shadows the name of the > structure and exports the constructor and the slot accessors. The macro > I wrote macroexpands into what I expect it to, for instance > > * (macroexpand-1 '(defstruct-shadow-export lambda slot)) > > (PROGN > (SHADOW 'LAMBDA) > (DEFSTRUCT LAMBDA SLOT) > (EXPORT 'MAKE-LAMBDA) > (EXPORT 'LAMBDA-SLOT)) > > but during the evaluation, I get an error saying: "[The] lock on package > COMMON-LISP [was] violated when defining LAMBDA as a structure". > > If after getting the error, I try to define the structure again, it > works as expected. It's as if the shadowing actually occured after the > evaluation of the progn. > > If any of you has an idea why this happens, and/or knows a way around > the problem... As Tim said, think about when things occur, read-time vs. run-time. What do you think about the two occurences of the symbol LAMBDA in this form? The way around it is obvious, if you can read the above question. -- __Pascal Bourguignon__
From: Thomas A. Russ on 3 May 2010 20:37 Jonathan Braud <jonathan.braud.NOSPAMTHANKYOUVERYMUCH+usenet(a)gmail.com> writes: > Hello everyone, > > I'm trying to write a version of defstruct that shadows the name of the > structure and exports the constructor and the slot accessors. The macro > I wrote macroexpands into what I expect it to, for instance > > * (macroexpand-1 '(defstruct-shadow-export lambda slot)) > > (PROGN > (SHADOW 'LAMBDA) > (DEFSTRUCT LAMBDA SLOT) > (EXPORT 'MAKE-LAMBDA) > (EXPORT 'LAMBDA-SLOT)) > > but during the evaluation, I get an error saying: "[The] lock on package > COMMON-LISP [was] violated when defining LAMBDA as a structure". > > If after getting the error, I try to define the structure again, it > works as expected. It's as if the shadowing actually occured after the > evaluation of the progn. > > If any of you has an idea why this happens, and/or knows a way around > the problem... I'll try to be less cryptic than Pascal and Tim. :-) The key, as they hint is that there is an issue with read-time verus evaluation time. When the reader encounters the form (macroexpand-1 '(defstruct-shadow-export lambda slot)) the first time, it reads the string "lambda" and interns it, which results in getting the symbol CL:LAMBDA back. This is the symbol that is then passed to your macro, and which is used in the expansion. One way to kind of see what is happening is to do something like (let ((*package* (find-package :keyword))) (print (macroexpand-1 '(defstruct-shadow-export lambda slot)))) I arbitrarily chose the KEYWORD package to essentially force the printer to print all of the symbols with their full package qualification. So this will let you see exactly which symbols you are dealing with. Essentially what is happening is that lisp has already read the string "lambda" and turned it into CL:LAMBDA before the macro gets a chance to do anything. It is only after the first execution of the code returned by your macro expansion that "LAMBDA" is shadowed in your own code So the second time you try the expansion, when the reader see "lambda" and interns it, it gets a different symbol, namely CL-USER::LAMBDA (or whatever package you are experimenting in instead of CL-USER). Your problem, then, is to figure out how to get the symbol you want to shadow to be shadowed at read time rather than at macro-expansion time. It may be sufficient to have the macro expansion function also shadow the symbol and do the substitution during macro-expansion. I don't have the time to figure out for sure if this would work, but I think it is a promising alternative to trying to do something using the reader. You will have to make sure, though, that you shadow the symbol and then substitute the symbol from the correct package for the name of the defstruct. Assuming that will work, you can try something like (defmacro defstruct-shadow-export (name &rest slots) ... (shadow name) (let ((new-name (intern (symbol-name name)))) `(progn (shadow ',name) (defstruct ,new-name ...) (export ...) ...))) -- Thomas A. Russ, USC/Information Sciences Institute
From: Jonathan Braud on 4 May 2010 19:12
Thanks to the three of you. I guess it was high time I read a few things on how the reader actually reads! The solution Thomas gave appears to work. It's the way to do it that feels the most natural to me. Still, I tried to find one that involved read-time evaluation, and the only thing I could come up with was calling the macro like this: (defstruct-shadow-expand #.(progn (shadow 'lambda) 'lambda) ...) It obviously makes the macro quite inconvenient to use. So I'm wondering if you were thinking of something more clever. Although, unless I missed something again, I really don't see how a macro could have any impact on what happens at read time. |