Would you mind explaining me what's going on in the following
code when I'm trying to compile DD?
cl-user(1): (compile 'dd)
; While compiling dd:
Error: macro aa expects exactly 0 arguments. It was given 2 arguments: (bb
aa).
[condition type: program-error]
Restart actions (select using :continue):
0: Return to Top Level (an "abort" restart).
1: Abort entirely from this (lisp) process.
[1] cl-user(2):
The code is:
------------------------------------------------------------------------
(defvar *g* nil)
(defmacro aa ()
`(eval-when (:compile-toplevel :load-toplevel :execute)
(push 'aa *g*)))
(defmacro bb ()
`(eval-when (:compile-toplevel :load-toplevel :execute)
(push 'bb *g*)))
(defun cc ()
(push 'cc *g*))
(defun dd ()
(progn
#.(aa)
(cc)
#.(bb)))
------------------------------------------------------------------------
It's not an idle curiosity
There is LOCALLY-ENABLE-SQL-READER-SYNTAX and
RESTORE-SQL-READER-SYNTAX-STATE macros in CLSQL (both use
eval-when). If I arrange them like
(defun foo ()
#.(locally-enable-sql-reader-syntax)
#|| some code which needs this sytax ||#
#.(restore-sql-reader-syntax-state))
it works. However,
(defun bar ()
......
(progn
#.(locally-enable-sql-reader-syntax)
#|| some code which needs this sytax ||#
#.(restore-sql-reader-syntax-state)))
....
does not, and I can't understand why no matter how hard I
try. [Initially I would try prog2 instead of progn. The result was
even worse].
--
Vladimir Zolotykh
Vladimir Zolotykh wrote:
> Would you mind explaining me what's going on in the following
> code when I'm trying to compile DD?
> (defun dd ()
> (progn
> #.(aa)
> (cc)
> #.(bb)))
Hint #1: the macro call (aa) expands into (push 'aa *g*) which is
evaluated at read-time by #. and the return value of that push is the
form that ends up in the code.
Hint #2: What does (push 'aa *g*) return?
If you want to evaluate #.(aa) only for a read-time side-effect, make
sure that whatever it returns is harmless when inserted as a form into
the code.
Vladimir Zolotykh <······@eurocom.od.ua> writes:
> (defun dd ()
> (progn
> #.(aa)
> (cc)
> #.(bb)))
If you put a quote at the front of the whole DEFUN form, you'll
see it was read as:
(DEFUN DD () (PROGN (AA) (CC) (BB AA)))
Do the same again and this time it'll be:
(DEFUN DD () (PROGN (AA BB AA) (CC) (BB AA BB AA)))
The #. reader macro does not discard the result of the evaluation.
If you want a reader macro that evaluates a form at read time but
is otherwise treated as a comment, I think it is easiest to write
your own. In some implementations, #.(progn (aa) (values)) gives
this effect, but I believe such implementations do not conform to
the standard.
In some contexts, you could do this instead:
(defun dd ()
(prog2
'#.(aa)
(cc)
'#.(bb)))
i.e. first prevent further evaluation and then discard the values.
Thank you both for your explanations
Had I used (push 1 *g*) instead of (push 'aa *g*) I would probably have
seen my
fault myself. It is also clear now why PROG2 didn't work. At the time of
evaluation
nothing was left from #.(...) forms and PROG2 complained justly.
The contruct like
(progn
#.(clsql:locally-enable-sql-reader-syntax)
code using [...] syntax>
#.(clsql:resore-sql-reader-syntax-state))
is unimpeachable and sould work at any nested level.
--
Vladimir Zolotykh