Hi
I am reading OnLisp trying to learn macros.
I am having trouble with the following two
;;pp. 145
;;evaluate a body with bunch of symbols in list syms set to gensyms
(defmacro with-gensyms (syms &body body)
`(let ,(mapcar #�(lambda (s)
`(,s (gensym)))
syms)
,@body))
;;pp. 169
;;sets a bunch of varibales in args to the value val
(defmacro allf (val &rest args)
(with-gensyms (gval)
`(let ((,gval ,val))
(setf ,@(mapcan #�(lambda (a) (list a gval))
args)))))
They seem to work fine in clisp (2.30)
In cmucl I am having problems trying to use allf.
I have a test file with just these two called test2.lisp
Here is what I get (i have stripped some empty lines here)
---------------------------------------------------------
CMU Common Lisp 18e, running on xxxxx
With core: /usr/lib/cmucl/lib/lisp.core
Dumped on: Thu, 2003-04-03 05:47:12-08:00 on orion
See <http://www.cons.org/cmucl/> for support information.
Loaded subsystems:
Python 1.1, target Intel x86
CLOS 18e (based on PCL September 16 92 PCL (f))
* (compile-file "test2.lisp")
; Python version 1.1, VM version Intel x86 on 18 MAY 04 05:58:46 pm.
; Compiling: xxxxx/test2.lisp 18 MAY 04 05:47:20 pm
; File: xxxxxx/test2.lisp
; In: DEFMACRO WITH-GENSYMS
; (MAPCAR #<Interpreted Function # {48029741}> SYMS)
; --> LET
; ==>
; #<Interpreted Function (LAMBDA # `#) {48029741}>
; Error: Cannot dump objects of type EVAL:INTERPRETED-FUNCTION into fasl
files.
;
; Converted WITH-GENSYMS.
; File: /u/antony/test2.lisp
; In: DEFMACRO WITH-GENSYMS
; `(LET (COMMON-LISP::BACKQ-COMMA #)
; ,@BODY)
; --> LIST*
; ==>
; BODY
; Note: Deleting unreachable code.
; (MAPCAR #<Interpreted Function # {48029741}> SYMS)
; --> LET LET DO-ANONYMOUS BLOCK LET
; ==>
; SYMS
; Note: Deleting unreachable code.
; Compiling DEFMACRO WITH-GENSYMS:
; File: /u/antony/test2.lisp
; In: DEFMACRO ALLF
; (MAPCAN #<Interpreted Function # {480BDF11}> ARGS)
; --> LET
; ==>
; #<Interpreted Function (LAMBDA # #) {480BDF11}>
; Error: Cannot dump objects of type EVAL:INTERPRETED-FUNCTION into fasl
files.
;
; Converted ALLF.
; File: /u/antony/test2.lisp
; In: DEFMACRO ALLF
; (MAPCAN #<Interpreted Function # {480BDF11}> ARGS)
; --> LET LET DO-ANONYMOUS BLOCK LET
; ==>
; ARGS
; Note: Deleting unreachable code.
;
; Compiling DEFMACRO ALLF:
; Byte Compiling Top-Level Form:
; Compilation unit finished.
; 2 errors
; 3 notes
; test2.x86f written.
; Compilation finished in 0:00:00.
#p"/u/antony/test2.x86f"
T
T
----------------------------------------------------------------
allf simply fails to work
I noticed that
* (macroexpand '(with-gensyms ( x y z) (+ x y z)))
;
(LET ((X (GENSYM)) (Y (GENSYM)) (Z (GENSYM)))
(+ X Y Z))
T
looks to be fine on cmucl.
Whereas allf fails -
* (setf a 1 b 2 c 3)
;
Warning: Declaring A special.
Warning: Declaring B special.
Warning: Declaring C special.
3
* (allf 10 x y z)
;
; Warning: This variable is undefined:
; GVAL
Error in KERNEL::UNBOUND-SYMBOL-ERROR-HANDLER: the variable GVAL is
unbound.
.........
The code also seems to be undumpable as a fasl file in cmucl.
I have a feeling that I may have to learn about eval-when.
Can someone explain what is going on.
Thanks,
-Antony
In article <···················@newssvr29.news.prodigy.com>,
Antony Sequeira <·············@hotmail.com> wrote:
> Hi
> I am reading OnLisp trying to learn macros.
> I am having trouble with the following two
>
> ;;pp. 145
> ;;evaluate a body with bunch of symbols in list syms set to gensyms
> (defmacro with-gensyms (syms &body body)
> `(let ,(mapcar #�(lambda (s)
> `(,s (gensym)))
> syms)
> ,@body))
>
> ;;pp. 169
> ;;sets a bunch of varibales in args to the value val
> (defmacro allf (val &rest args)
> (with-gensyms (gval)
> `(let ((,gval ,val))
> (setf ,@(mapcan #�(lambda (a) (list a gval))
> args)))))
Since WITH-GENSYMS is being used in the computation of the macro, not
its expansion, you need to ensure that the definition is in the
compile-time environment. So you have to use EVAL-WHEN:
(eval-when (:compile-toplevel :load-toplevel :execute)
(defmacro with-gensyms ...))
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Barry Margolin wrote:
> In article <···················@newssvr29.news.prodigy.com>,
> Antony Sequeira <·············@hotmail.com> wrote:
>>Hi
>>I am reading OnLisp trying to learn macros.
>>I am having trouble with the following two
>>
>>;;pp. 145
>>;;evaluate a body with bunch of symbols in list syms set to gensyms
>>(defmacro with-gensyms (syms &body body)
>> `(let ,(mapcar #�(lambda (s)
>> `(,s (gensym)))
>> syms)
>> ,@body))
>>
>>;;pp. 169
>>;;sets a bunch of varibales in args to the value val
>>(defmacro allf (val &rest args)
>> (with-gensyms (gval)
>> `(let ((,gval ,val))
>> (setf ,@(mapcan #�(lambda (a) (list a gval))
>> args)))))
>
>
> Since WITH-GENSYMS is being used in the computation of the macro, not
> its expansion, you need to ensure that the definition is in the
> compile-time environment. So you have to use EVAL-WHEN:
>
> (eval-when (:compile-toplevel :load-toplevel :execute)
> (defmacro with-gensyms ...))
>
Thank you, that worked.
Now I am trying to understand what is going on.
Is the eval needed because 'allf' executes 'with-gensyms' during the
generation of the expansion (I know I am likely rephrasing what you said
already)?
So it is the allf macro that is the cause of the issue and not the
with-gensyms macro ?
Assuming I understand correctly, I find this interesting, cause it
implies if I were to write a macro that needs to use another macro (that
is say in a third party library), I have to be able to change its eval
time to use it. How is that done ?
-Antony
Antony Sequeira wrote:
> Assuming I understand correctly, I find this interesting, cause it
> implies if I were to write a macro that needs to use another macro (that
> is say in a third party library), I have to be able to change its eval
> time to use it. How is that done ?
If it's in a different library, you can just first load that library,
and then go on.
Pascal
--
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
Pascal Costanza wrote:
>
>
> Antony Sequeira wrote:
>
>> Assuming I understand correctly, I find this interesting, cause it
>> implies if I were to write a macro that needs to use another macro
>> (that is say in a third party library), I have to be able to change
>> its eval time to use it. How is that done ?
>
>
> If it's in a different library, you can just first load that library,
> and then go on.
>
>
> Pascal
>
I put the two macros in different files, compiled in appropriate order
without using eval-when. That worked.
Now I am a bit confused. I only called compile-file on files that
contained the two macros with-gensyms and allf, one in each file. I did
not call load.
How come the cmucl REPL allows me to run the macro allf. Does this mean
compile-file has the side effects of defining the macros and not just
compiling ? But the functions get defined only after load ?
So, would the rule for builds be
1. If a macro X reuqires macro Y for expansion, you have to *compile*
the file with macro Y first.
2. If a macro X requires a function Z, you have to *compile and load*
the file with Z before compiling the file with X. (ignoring it is
possible to use load without having compiled)
Am I getting this right ?
Thanks for the help.
-Antony
Antony Sequeira wrote:
> I put the two macros in different files, compiled in appropriate order
> without using eval-when. That worked.
> Now I am a bit confused. I only called compile-file on files that
> contained the two macros with-gensyms and allf, one in each file. I did
> not call load.
> How come the cmucl REPL allows me to run the macro allf. Does this mean
> compile-file has the side effects of defining the macros and not just
> compiling ? But the functions get defined only after load ?
I don't know - that's a question for the CMUCL developers.
> So, would the rule for builds be
> 1. If a macro X reuqires macro Y for expansion, you have to *compile*
> the file with macro Y first.
> 2. If a macro X requires a function Z, you have to *compile and load*
> the file with Z before compiling the file with X. (ignoring it is
> possible to use load without having compiled)
> Am I getting this right ?
The COMPILE-FILE entry in the HyperSpec doesn't say anything about
automatically loading definitions, so this seems to be
implementation-specific behavior that you probably cannot rely on when
switching to a different CL implementation.
Your questions suggest that you might want to take a look at one of the
various system definition facilities, like ASDF and MK:DEFSYSTEM
Pascal
--
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
>>>>> "as" == Antony Sequeira <·············@hotmail.com> writes:
as> How come the cmucl REPL allows me to run the macro allf. Does this
as> mean compile-file has the side effects of defining the macros and not
as> just compiling ? But the functions get defined only after load ?
the phenomenom you are seeing can be called leakage from the
compile-time environment to the evaluation environment; the degree
of leakage is implementation-dependent. There is an entry on this
subject in the CMUCL FAQ.
<http://www.cons.org/cmucl/FAQ.html>
--
Eric Marsden <URL:http://www.laas.fr/~emarsden/>
Eric Marsden wrote:
>>>>>>"as" == Antony Sequeira <·············@hotmail.com> writes:
>
>
> as> How come the cmucl REPL allows me to run the macro allf. Does this
> as> mean compile-file has the side effects of defining the macros and not
> as> just compiling ? But the functions get defined only after load ?
>
> the phenomenom you are seeing can be called leakage from the
> compile-time environment to the evaluation environment; the degree
> of leakage is implementation-dependent. There is an entry on this
> subject in the CMUCL FAQ.
>
> <http://www.cons.org/cmucl/FAQ.html>
>
It is entry # 16 in the FAQ. Thanks for pointing.
-Antony