From: Vladimir Zolotykh
Subject: #.(puzzle)
Date: 
Message-ID: <opslt6mkez8k218c@news.eurocom.od.ua>
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 

From: Kaz Kylheku
Subject: Re: #.(puzzle)
Date: 
Message-ID: <1107798856.790696.80730@o13g2000cwo.googlegroups.com>
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.
From: Kalle Olavi Niemitalo
Subject: Re: #.(puzzle)
Date: 
Message-ID: <87oeewcjlj.fsf@Astalo.kon.iki.fi>
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.
From: Vladimir Zolotykh
Subject: Re: #.(puzzle)
Date: 
Message-ID: <opslvmilix8k218c@news.eurocom.od.ua>
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