Macrolet within defmacro question 
Author Message
 Macrolet within defmacro question

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)

                         (write-line "}" ,stream)))



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

Wade



Fri, 19 Apr 2002 03:00:00 GMT  
 Macrolet within defmacro question
* 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 ": {")

                   (write-line "}")))
              (BODY (&rest properties)

              (ROOT (&rest properties)

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

(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



Sat, 20 Apr 2002 03:00:00 GMT  
 Macrolet within defmacro question

Quote:

> 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)

>                          (write-line "}" ,stream)))



> ;; 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)

                  (write-line "}" ,,stream)))
             (BODY (&rest properties)

             (ROOT (&rest properties)


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



Sat, 20 Apr 2002 03:00:00 GMT  
 Macrolet within defmacro question
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 ": {")

                         (write-line "}")))


  (macroexpand `(let ((*standard-output* ,stream))

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



Sat, 20 Apr 2002 03:00:00 GMT  
 Macrolet within defmacro question



Quote:

> 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



Sat, 20 Apr 2002 03:00:00 GMT  
 Macrolet within defmacro question

Quote:

>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.

Quote:
>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 ": {")

>                         (write-line "}")))


>  (macroexpand `(let ((*standard-output* ,stream))

>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))

                  collect (expand-it element))))))

--

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.



Sat, 20 Apr 2002 03:00:00 GMT  
 Macrolet within defmacro question

Quote:

> 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.

--

  "One smaller motivation which, in part, stems from altruism is Microsoft-
   bashing." [Microsoft memo, see http://www.opensource.org/halloween1.html]



Sat, 20 Apr 2002 03:00:00 GMT  
 Macrolet within defmacro question

Quote:

> 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



Sun, 21 Apr 2002 03:00:00 GMT  
 Macrolet within defmacro question

Quote:



> > 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

Quote:
> 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....

Quote:
> 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


Sun, 21 Apr 2002 03:00:00 GMT  
 
 [ 9 post ] 

 Relevant Pages 

1. symbol-macrolet question (evil)

2. ANSI CL, DEFMACRO question

3. defmacro question

4. return-from / defmacro question

5. defmacro question

6. SYMBOL-MACROLET and special variables

7. macrolet

8. Does symbol-macrolet presuppose a codewalker?

9. Expand a macrolet form?

10. macrolet vs #.

11. LET and SYMBOL-MACROLET?

12. Macroexpand and symbol-macrolet

 

 
Powered by phpBB® Forum Software