Discussion:
Specifying prologues (and a digression into special variables)
Ken Harris
2008-10-26 00:15:40 UTC
Permalink
Hi,

I'm using cl-who for a project where I want to generate 2 kinds of
XML, and each has their own prologue. I started by passing these as
literals to the keyword parameter :prologue, but I'd like to pull them
out into constants, and eventually one will need to be computed at
runtime.

At first, I tried just passing an expression to :prologue, but that
obviously failed (because defmacro evaluates it at macroexpand-time,
not run-time, I think):

(defconstant +my-prologue+ "header")
(with-html-output-to-string (s nil :prologue +my-prologue+) (:a))
=>
"
<a></a>"

Then I went and read Erann Gat's "Idiot's Guide to Special Variables".
It doesn't mention macros, but I figured I could get close with
something like this, but no, it ignores my *prologue* setting:

(let ((*prologue* "header"))
(with-html-output-to-string (s nil :prologue t) (:a)))
=>
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
<a></a>"

So obviously I'm missing the boat on special variables and defmacro.
I know I could just setq *prologue* before calling cl-who (or even
cruder approaches), but that seems awkward, and I'd like to learn
what's going on with special variables and macros.

As an aside, special variables and macros aren't behaving the same in
my 2 Lisp implementations (all of the above is with SBCL), so it seems
that at least somebody out there thinks the same way as me: :-)

(defvar *special* 5)
(defun show-special () *special*)
(defmacro with-special () *special*)
(show-special)
(let ((*special* 10)) (show-special))
(with-special)
(let ((*special* 10)) (with-special))

;; CLISP 2.43: 5, 10, 5, 10
;; SBCL 1.0.13: 5, 10, 5, 5

If anybody could shed some light on this, and show how to most
naturally use an expression as a :prologue with cl-who, it'd be much
appreciated.

Thanks!


- Ken
Leslie P. Polzer
2008-10-26 12:07:48 UTC
Permalink
Dear Ken,
Post by Ken Harris
So obviously I'm missing the boat on special variables and defmacro.
I know I could just setq *prologue* before calling cl-who (or even
cruder approaches), but that seems awkward,
Awkward indeed! But if you put it into a well-separated function
it's not that bad.
Post by Ken Harris
and I'd like to learn what's going on with special variables and macros.
Yes, that's important.
Post by Ken Harris
As an aside, special variables and macros aren't behaving the same in
my 2 Lisp implementations (all of the above is with SBCL), so it seems
that at least somebody out there thinks the same way as me: :-)
(defvar *special* 5)
(defun show-special () *special*)
(defmacro with-special () *special*)
(show-special)
(let ((*special* 10)) (show-special))
(with-special)
(let ((*special* 10)) (with-special))
;; CLISP 2.43: 5, 10, 5, 10
;; SBCL 1.0.13: 5, 10, 5, 5
Don't take my word for it, but my guess is that you've
fallen right into the compiler/interpreter trap.

SBCL is a compiler-only implementation and CLISP
interprets code by default.

I'll leave it as an exercise to you what exactly happens
here.
Post by Ken Harris
If anybody could shed some light on this, and show how to most
naturally use an expression as a :prologue with cl-who, it'd be much
appreciated.
Not sure here either but take a look at the macro:

(defmacro with-html-output ((var &optional stream
&key prologue
((:indent *indent*) *indent*))
&body body)
(when (and *indent*
(not (integerp *indent*)))
(setq *indent* 0))
(when (eq prologue t)
(setq prologue *prologue*))
`(let ((,var ,(or stream var)))
,(tree-to-commands body var prologue)))

*prologue* gets evaluated at macro expansion time, and
I suppose special bindings are not in effect then.
Wild guess. Wade through the spec to find out.

Or maybe someone else can point it out.

The solution here is using macros to define your
own prologues.
Post by Ken Harris
Thanks!
Thanks for checking out Common Lisp!

Leslie
--
LinkedIn Profile: http://www.linkedin.com/in/polzer
Xing Profile: https://www.xing.com/profile/LeslieP_Polzer
Blog: http://blog.viridian-project.de/
Ken Harris
2008-10-27 21:12:13 UTC
Permalink
Hi Leslie,

Thanks for responding!

I think I'm still in detox from a long Ruby project. :-) I think I
was thinking that part of the macroexpansion would occur at runtime or
something. I'm now trying to use it more as it seems to have been
intended to be used.
Post by Leslie P. Polzer
The solution here is using macros to define your
own prologues.
Maybe, but for now, I'm just prepending my own prologue outside of the
(with-html-output...) call. I want to get something working fast, and
there are more interesting parts of the problem to attack.


- Ken

Loading...