Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Macrolet within defmacro question

32 views
Skip to first unread message

Wade Humeniuk

unread,
Nov 1, 1999, 3:00:00 AM11/1/99
to
I am using LWW 4.1.18 and I am trying to write the following macro. The
way it currently written it does not work. When I try the example below
the error message I get is that COLOR is not a function. This means
that the declare-html-style-sheet macro is not expanding the
macrolet definitions.

What am I doing wrong??? Can you do a
macrolet like this within a defmacro?

(defmacro declare-html-style-sheet ((type-of-ss &key (stream
*standard-output*))
&rest elements &environment env)
(macrolet ((COLOR (color-value) `(progn
(write-string "color: " ,stream)
(write-string (string-downcase
,color-value) ,stream)
(write-char #\; ,stream)))
(ELEMENT (element-name &rest properties)
`(progn
(write ,element-name ,stream)
(write-line ": {" ,stream)
,@properties
(write-line "}" ,stream)))
(BODY (&rest properties) `(ELEMENT 'BODY ,@properties))
(ROOT (&rest properties) `(ELEMENT '* ,@properties)))
`(progn ,@elements)))

;; Example
(declare-html-style-sheet (:css2 :stream stream)
(ROOT (color :tan))
(BODY (color :olive)))

Wade

Erik Naggum

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to
* Wade Humeniuk

| Can you do a macrolet like this within a defmacro?

yes, but remember that a macro is really an ordinary function, it is just
called at a different time than other functions. specifically, the macro
is called with the form in question to yield the expansion, which is
simply a new form as seen by the recipient of the value -- as with any
other function, whatever was in scope _inside_ that function is gone when
you exit it. to capture something, the function needs to be in the scope
of whatever you want to capture.

| What am I doing wrong???

you're trying to use macros that are no longer in scope.

the following should work as you expect, as it makes the macros visible
in the _expanded_ form. note that this doesn't have any significant
cost. to look at the results, I use Allegro CL's walker (excl::walk) --
LWW probably has something similar that lets you macroexpand an entire
form recursively and reduce the noise.

(defmacro declare-html-style-sheet ((type-of-ss &key (stream '*standard-output*))
&rest elements &environment env)

(declare (ignore type-of-ss env))
`(macrolet ((COLOR (color-value)
`(progn
(write-string "color: ")
(write-string (string-downcase ,color-value))
(write-char #\;)))


(ELEMENT (element-name &rest properties)
`(progn

(write ,element-name)
(write-line ": {")
,@properties
(write-line "}")))


(BODY (&rest properties)
`(ELEMENT 'BODY ,@properties))
(ROOT (&rest properties)
`(ELEMENT '* ,@properties)))

(let ((*standard-output* ,stream))
,@elements)))

(excl::walk '(declare-html-style-sheet (:css2 :stream *standard-output*)
(ROOT (COLOR :tan))
(BODY (COLOR :olive))))
=> (progn
(let ((*standard-output* *standard-output*))
(progn
(write '*)
(write-line ": {")
(progn
(write-string "color: ")
(write-string (string-downcase :tan))
(write-char #\;))
(write-line "}"))
(progn
(write 'BODY)
(write-line ": {")
(progn
(write-string "color: ")
(write-string (string-downcase :olive))
(write-char #\;))
(write-line "}"))))

stylistically, I don't think exploiting the case insensitivity of Common
Lisp is such a good idea. it's better to stick to one form of a symbol.

#:Erik

Christopher R. Barry

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to
"Wade Humeniuk" <hume...@cadvision.com> writes:

> I am using LWW 4.1.18 and I am trying to write the following macro. The
> way it currently written it does not work. When I try the example below
> the error message I get is that COLOR is not a function. This means
> that the declare-html-style-sheet macro is not expanding the
> macrolet definitions.
>

> What am I doing wrong??? Can you do a


> macrolet like this within a defmacro?
>

> (defmacro declare-html-style-sheet ((type-of-ss &key (stream
> *standard-output*))
> &rest elements &environment env)

> (macrolet ((COLOR (color-value) `(progn


> (write-string "color: " ,stream)
> (write-string (string-downcase
> ,color-value) ,stream)
> (write-char #\; ,stream)))

> (ELEMENT (element-name &rest properties)
> `(progn

> (write ,element-name ,stream)
> (write-line ": {" ,stream)
> ,@properties
> (write-line "}" ,stream)))

> (BODY (&rest properties) `(ELEMENT 'BODY ,@properties))
> (ROOT (&rest properties) `(ELEMENT '* ,@properties)))

> `(progn ,@elements)))
>
> ;; Example
> (declare-html-style-sheet (:css2 :stream stream)
> (ROOT (color :tan))
> (BODY (color :olive)))


Didn't you _read_ the warnings I'm sure LispWorks gave you when you
compiled that macro about arguments not getting used? TYPE-OF-SS
doesn't even _appear_ anywhere. Since the DEFMACRO does not expand
into the MACROLET, the definitions that the MACROLET creates are only
going to exist during macroexpand time. Once the macroexpansion of
DECLARE-HTML-STYLE-SHEET is done, the MACROLET will no longer exist.
Did you even try macroexpanding your example?

One of the most fundamental rules of writing macros is that you must
have a _very clear_ idea of what you want to expand to, or you deserve
to lose. Here's a quick rewrite that macroexpands correctly:

(defmacro declare-html-style-sheet ((type-of-ss
&key (stream *standard-output*))

&body elements)
`(macrolet ((COLOR (color-value)
`(progn
(write-string "color: " ,,stream)
(write-string (string-downcase ,color-value) ,,stream)
(write-char #\; ,,stream)))


(ELEMENT (element-name &rest properties)
`(progn

(write ,element-name :stream ,,stream)
(write-line ": {" ,,stream)
,@properties
(write-line "}" ,,stream)))


(BODY (&rest properties)
`(ELEMENT 'BODY ,@properties))
(ROOT (&rest properties)
`(ELEMENT '* ,@properties)))

(progn ,@elements)))


I made a few cosmetic touch-ups, like using &BODY instead of &REST so
that editors indent it properly, as well as a few quick bug-fixes
completely unrelated to macroexpansion.

I did not fix your fundamental design errors, however. I have fairly
thorough knowledge of CSS2 and all the DHTML junk, and the approach
you are taking isn't going to get you where you want to go. Do a
DejaNews search for a posting from Paul Foley that shows (with much
code) how to basically go about doing this kind of thing. (He does
this with HTML).

Christopher


Wade Humeniuk

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to
Thanks Erik. The solution makes be a bit
quesy, as the macrolet (which will get quite large)
has to processed for every occurence of the macro.

Is there any way of doing it without quasiquoting the macrolet?
Besides making color, element, body and root top level
macros in themselves?

I have tried:

(defmacro declare-html-style-sheet ((type-of-ss &key (stream
*standard-output*))
&rest elements &environment env)

(macrolet ((color (color-value)


`(progn
(write-string "color: ")
(write-string (string-downcase ,color-value))
(write-char #\;)))

(element (element-name &rest properties)
`(progn


(write ,element-name)
(write-line ": {")
,@properties
(write-line "}")))

(body (&rest properties) `(element 'body ,@properties))
(root (&rest properties) `(element '* ,@properties)))
(macroexpand `(let ((*standard-output* ,stream))
,@elements))))

but it doesn't seem to work either.

The following example from the online ANSI CL Hyperspec suggests with this
example that the above code should work

(defmacro alpha (x y) `(beta ,x ,y)) => ALPHA
(defmacro beta (x y) `(gamma ,x ,y)) => BETA
(defmacro delta (x y) `(gamma ,x ,y)) => EPSILON

(macrolet ((alpha (x y) `(delta ,x ,y)))
(macroexpand '(alpha a b))) => (GAMMA A B), true

Wade


Wade Humeniuk

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to

Christopher R. Barry <cba...@2xtreme.net> wrote in message
news:87ogddq...@2xtreme.net...

>
> I did not fix your fundamental design errors, however. I have fairly
> thorough knowledge of CSS2 and all the DHTML junk, and the approach
> you are taking isn't going to get you where you want to go. Do a
> DejaNews search for a posting from Paul Foley that shows (with much
> code) how to basically go about doing this kind of thing. (He does
> this with HTML).

Thanks.

My local news archives have nothing with Paul Foley. Is his code
to become part of cl-http for css2?

Could you give me some examples of style sheets that would
not work with an interface like declare-html-style-sheet? Forget for a
minute
my actual simplistic implementation code.

Here is an example written in the style I am thinking of.

(declare-html-style-sheet (:css2)
(import (url "http://theworld.org/basic.css"))
(body (color :mediumseagreen) (font-family :arial))
(h2 (margin-top (length 140 :units :px)))
(h2 i (color :red))
(h2 b (background :yellow))
(new-style-class style1
(color :black)
(margin-top: (length -80 :units :px))

Wade

Barry Margolin

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to
In article <381f...@news.cadvision.com>,

Wade Humeniuk <hume...@cadvision.com> wrote:
>Thanks Erik. The solution makes be a bit
>quesy, as the macrolet (which will get quite large)
>has to processed for every occurence of the macro.

So? This only happens at compile time.

>I have tried:
>
>(defmacro declare-html-style-sheet ((type-of-ss &key (stream
>*standard-output*))
> &rest elements &environment env)
> (macrolet ((color (color-value)
> `(progn
> (write-string "color: ")
> (write-string (string-downcase ,color-value))
> (write-char #\;)))
> (element (element-name &rest properties)
> `(progn
> (write ,element-name)
> (write-line ": {")
> ,@properties
> (write-line "}")))
> (body (&rest properties) `(element 'body ,@properties))
> (root (&rest properties) `(element '* ,@properties)))
> (macroexpand `(let ((*standard-output* ,stream))
> ,@elements))))
>
>but it doesn't seem to work either.

MACROEXPAND is expanding in the top-level lexical environment. This is
analogous to binding local variables and functions with LET and FLET, and
then calling EVAL -- it can't access the local bindings.

Another problem is that MACROEXPAND only expands macro invocations at the
top-level of the form, it doesn't dive into the body of the LET to expand
the forms in its body.

I notice that you have an &environment parameter to your macro, but you
never use it. I suspect you intended to pass it as the second argument to
MACROEXPAND. However, this wouldn't have solved your problem, as that
would be the environment in which DECLARE-HTML-STYLE-SHEET was invoked, not
the environment inside the MACROLET.

Maybe something like this would work (I haven't tried it):

(defmacro declare-html-style-sheet (...)
(macrolet (...)
(macrolet ((expand-it (form &environment env)
(macroexpand form env)))
`(let ((*standard-output* ,stream))
,@(loop for element in elements
collect (expand-it element))))))

--
Barry Margolin, bar...@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

Pierre R. Mai

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to
"Wade Humeniuk" <hume...@cadvision.com> writes:

> Thanks Erik. The solution makes be a bit
> quesy, as the macrolet (which will get quite large)
> has to processed for every occurence of the macro.

Why do you care so much about the time it takes to _compile_ your code?
Is it so much (or the compiler so slow) that this really matters?

Regs, Pierre.

--
Pierre Mai <pm...@acm.org> PGP and GPG keys at your nearest Keyserver
"One smaller motivation which, in part, stems from altruism is Microsoft-
bashing." [Microsoft memo, see http://www.opensource.org/halloween1.html]

Christopher R. Barry

unread,
Nov 3, 1999, 3:00:00 AM11/3/99
to
"Wade Humeniuk" <hume...@cadvision.com> writes:

> Is there any way of doing it without quasiquoting the macrolet?
> Besides making color, element, body and root top level
> macros in themselves?

Did you search for the Paul Foley post in DejaNews?

Christopher

Christopher R. Barry

unread,
Nov 3, 1999, 3:00:00 AM11/3/99
to
"Wade Humeniuk" <hume...@cadvision.com> writes:

> Christopher R. Barry <cba...@2xtreme.net> wrote in message
> news:87ogddq...@2xtreme.net...
> >
> > I did not fix your fundamental design errors, however. I have fairly
> > thorough knowledge of CSS2 and all the DHTML junk, and the approach
> > you are taking isn't going to get you where you want to go. Do a
> > DejaNews search for a posting from Paul Foley that shows (with much
> > code) how to basically go about doing this kind of thing. (He does
> > this with HTML).
>
> Thanks.
>
> My local news archives have nothing with Paul Foley.

I explicitly told you to use DejaNews:
http://www.deja.com/getdoc.xp?AN=505266645&fmt=text


> Could you give me some examples of style sheets that would not work
> with an interface like declare-html-style-sheet? Forget for a minute
> my actual simplistic implementation code.

The approach you have taken with your implementation code was
precisely what I was criticizing. Use Paul Foley's code as a starting
point for your own. (The license appears to be Public Domain.)

At a brief glance your syntax looks like it will get the job done....

> Here is an example written in the style I am thinking of.
>
> (declare-html-style-sheet (:css2)
> (import (url "http://theworld.org/basic.css"))
> (body (color :mediumseagreen) (font-family :arial))
> (h2 (margin-top (length 140 :units :px)))
> (h2 i (color :red))
> (h2 b (background :yellow))
> (new-style-class style1
> (color :black)
> (margin-top: (length -80 :units :px))


Christopher

0 new messages