Re: macro that writes macros



On Dec 30, 4:46 am, Leandro Rios <leandroprograma...@xxxxxxxxx> wrote:
jordi.burguet.cast...@xxxxxxxxx escribió:



Hi,

I'm learning lisp and tried to make this little program to write a web
page:

(defmacro new-tag (name)
(let ((sname (string-downcase (symbol-name name))))
`(defmacro ,name (&rest content)
`(progn
(format t "<~a>~%" ,',sname)
,@content
(format t "</~a>~%" ,',sname)))))

(new-tag html)
(new-tag head)
(new-tag title)
(new-tag body)
(new-tag p)

;; With that, now a web page can be "self-generated":
(html
(head
(title "My web page"))
(body
(p "Hello world")))

And it works. But then I thought about combining all those "(new-
tag ...)" like this:

Em, no, it does not. When I run your code with your example I get:

<html>
<head>
<title>
</title>
</head>
<body>
<p>
</p>
</body>
</html>

You're omitting to print the strings. The macroexpansion of (new-tag
title) is (try macroexpand and macroexpand-1):

(DEFMACRO TITLE (&REST CONTENT)
`(PROGN (FORMAT T "<~a>~%" "title") ,@CONTENT (FORMAT T "</~a>~%"
"title")))

And that of (title "My web page") results in:

(PROGN (FORMAT T "<~a>~%" "title") "My web page" (FORMAT T "</~a>~%"
"title"))

As you can see, the string "My web page" isn't going to the same stream
as the tags (in this case standard output). In fact, it's going nowhere.

I modified your version so it prints the string when present:

(defmacro new-tag (name)
(let ((sname (string-downcase (symbol-name name))))
`(defmacro ,name (&rest content)
`(progn
(format t "<~a>~%" ,',sname)
(if (typep (car ',content) 'string)
(format t "~A~%" (car ',content))
(progn ,@content))
(format t "</~a>~%" ,',sname)))))

Now the output seems correct:

<html>
<head>
<title>
My web page
</title>
</head>
<body>
<p>
Hello world
</p>
</body>
</html>

Others have already showed how to fix new-tags.

Happy lisping and happy new year.

Leandro

Yes, you are right, I was so concerned with the second macro that I
didn't notice it. Your solution works nicely. Thank you!

jordi
.