Is there any other way(I mean situations that a macro exapnsion might be performed) to perform a macro expansion multiple times during EVAL?

sorry for my bad english

     Best regards,
Xiaofeng Yang

2014-02-28 19:15 GMT+08:00 Xiaofeng Yang <>:
There is a message by
Nikodemus Siivola (nikodemus) wrote on 2010-03-19: #1

Strictly speaking IIRC, macros are allowed to be expanded multiple times, what is going on here seems unintentional.

But I don't understand the meaning of 'macros are allowed to be expanded multiple times' here.
For what I know, during EVAL, when a macro form is encountered, then a macro expansion is performed (in once). This macro-expansion is controlled by *macroexpand-hook*, so that the macro function might be called in any times during the execution of *macroexpand-hook* in this macro expansion. When the result form is also a macro form, then additional macro expansions will be performed.
Is there any other way to perform a macro expansion multiple times during EVAL?

And after that message, there is another message:
summary: - incorrect macro evaluation
+ EVAL occasionally expands macros twice

Is this execution is correct ? I saw that in the code is firstly MACROEXPAND a macro, then when the condition of compilation is encountered, it compiles the origin code. During the compilation, the macro will be expanded the second time. Like the following shows.

In file bbb.lisp:
(in-package :cl-user)

(defvar *counting-1* 0)
(defvar *counting-2* 0)
(defvar *counting-hook* 0)

(defmacro test1 ()
  (incf *counting-1*)
  '(quote (1 2 3)))

(defmacro test2 ()
  (incf *counting-2*)
  '(setq *a* 1 *b* 2 *c* 3))            ; make it compiles me

(defun get-values ()
  (print (list *counting-1* *counting-2* *counting-hook*)))

(setf *macroexpand-hook* (lambda (&rest args)
                           (print args)
                           (incf *counting-hook*)
                           (apply #'funcall args)))

Run sbcl:
$ ~/sbcl/bin/sbcl
This is SBCL 1.1.14, an implementation of ANSI Common Lisp.
More information about SBCL is available at <>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
* (load "bbb.lisp")

* (test2)                        

(#<FUNCTION (MACRO-FUNCTION TEST2) {100390847B}> (TEST2) #<NULL-LEXENV>)     ;  <-- the first macro expansion during evaluation, the result is (setq *a* 1 *b* 2 *c* 3), so the compilation of (test2) is performed
(#<FUNCTION (MACRO-FUNCTION TEST2) {100390847B}> (TEST2)      ; <-- the macro expansion is performed the second time with a different environment
              :%SOURCE-NAME SB-C::.ANONYMOUS.
              :%DEBUG-NAME (LAMBDA ())
              :KIND NIL
              :TYPE #<SB-KERNEL:BUILT-IN-CLASSOID FUNCTION (read-only)>
              :WHERE-FROM :DEFINED
              :VARS NIL {10039820C3}>
              (SAFETY . 1) (SPACE . 1) (SPEED . 1))
; in: TEST2
;     (TEST2)
; --> SETQ
; ==>
;   (SETQ *A* 1)
; caught WARNING:
;   undefined variable: *A*

; ==>
;   (SETQ *B* 2)
; caught WARNING:
;   undefined variable: *B*

; ==>
;   (SETQ *C* 3)
; caught WARNING:
;   undefined variable: *C*
; compilation unit finished
;   Undefined variables:
;     *A* *B* *C*
;   caught 3 WARNING conditions
* (get-values)

(0 2 2)               ;  <-- the *macroexpand-hook* and the same macro function are both called twice
(0 2 2)
* (test1)             ;  <-- the result of this macro is (quote ...), so the compilation does not be performed, thus the execution of the macro function and *macroexpand-hook* both are only once

(1 2 3)
* (get-values)

(1 2 3)
(1 2 3)

I've googled but found nothing.

     Best regards,
Xiaofeng Yang