Subject: Re: macro and cl-who help
From: rpw3@rpw3.org (Rob Warnock)
Date: Tue, 12 May 2009 20:30:58 -0500
Newsgroups: comp.lang.lisp
Message-ID: <XfGdnWp2UP9Pv5fXnZ2dnUVZ_vCdnZ2d@speakeasy.net>
Alessio Stalla  <alessiostalla@gmail.com> wrote:
+---------------
| totua...@gmail.com wrote:
| > Why this does not work?
| >
| > (defmacro a-frm ()
| >   `(:br))
| >
| > (defun reply ()
| >   (with-html-output (*standard-output* nil)
| >      (:html (:body (a-frm)))))
| >
| > When i run (reply) , I get error : The function :BR is undefined.
| > Why it does not became (:html (:body (:br)))
| 
| It's been a while since I've used cl-who, but:
| I believe this happens because cl-who uses a limited "code-walker"
| that transforms all forms which have keyword as car into html print
| statements (sort of). This code walker does not do macroexpansions
| (probably because getting macroexpansions right is not that easy to do).
| So when it sees (a-frm) it says, no keyword! let's leave it alone.
+---------------

All correct so far...

+---------------
| IIRC if you wrap your macro call in an htm form like this:
| (htm (a-frm)) it should do what you want.
+---------------

Unfortunately, that won't work, either! Yes, the appearance of the
(HTM ...) form will force the outer W-H-O to treat the HTM form as
Lisp, but... but... HTM is itself just a macro[1] which just bounces
you back into the "walking forms as HTML data" mode, and so HTM won't
parse the A-FRM, *either*!!

To make this work[2], you have to change your A-FRM macro to include
the HTM inside *it*:

    > (defmacro a-frm ()
	`(htm (:br)))

    A-FRM
    > (defun reply ()
	(with-html-output (*standard-output* nil)
	  (:html
	    (:body (a-frm)))))

    REPLY
    > (reply)
    <HTML><BODY><BR></BODY></HTML>
    > 

It's even messier when the nested thing is a function. In that
case you have to re-open the whole W-H-O context from scratch:

    > (defun a-frm2 ()
	(with-html-output (*standard-output* nil)
	  (:br)))

    A-FRM2
    > (defun reply2 ()
	(with-html-output (*standard-output* nil)
	  (:html
	    (:body (a-frm2)))))

    REPLY2
    > (reply2)
    <HTML><BODY><BR></BODY></HTML>
    > 


-Rob

[1] Strictly speaking, HTM is a MACROLET defined by the outer W-H-O.

[2] Note that the above fixes were actually tested on HTOUT, rather
    than CL-WHO, but AFAIK they *should* work for CL-WHO as well.

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607