<hjstein@gmail.com> wrote:
+---------------
| It's not uncommon to see an embedded language in CL in macro style,
| as in:
| (html:output (html:body ...))
| when one could instead use a function, as in:
| (html:output '(html:body ...))
+---------------
But if the body is a constant, as you've shown here, how does
one insert dynamically-calculated HTML or even dynamically-
calculated plain text into the body?!? That is, how do you do
the equivalent of this in your "function" form [taken from
<http://rpw3.org/hacks/lisp/appsrv-demo.lhp>] ?
(lhp-basic-page () ; defaults to HTOUT-2.1 syntax
(:html ()
(:head () (:title () title))
(lfd)
(:body (:bgcolor "#ffffff") (lfd)
...[details elided]...
;; Show the results, first a number and its powers in a row.
(:table () (lfd)
(:tr () (loop for e from 1 to pows and h in headings do
(let ((p (cond ((= e 1) ":") ((= e pows) "") (t ","))))
(htm (:th (:nowrap) (fmt h e) p)))))
(loop for i from 1 to nums do
(htm (lfd) (:tr (:align "right")
(loop for e from 1 to pows do
(htm (:td () (princ (expt i e) lhp-stream))))))))
...[details elided]...)))
+---------------
| One advantage of the macro style is efficiency - the call expands at
| compile time and can be compiled with full optimization. The macro
| can be written in such a way that it expands to reasonably efficient code.
+---------------
Another *major* advantage of what you're calling "the macro style" is
that one has full access to the full Common Lisp environment at both
macro-expansion time *and* run-time, and can easily interweave the
HTML-generating macros with other more-complex or more-general Common
Lisp code. [See my example above.]
In order to obtain the same flexibility from "the function style",
you'd need to make the arguments of the function be closures,
not constants, so you could do stuff like this [the above <TABLE>
example transliterated into a non-macro "function style"]:
(html:table
(lambda ()
(html:tr
(lambda ()
(loop for e from 1 to pows and h in headings do
(let ((p (cond ((= e 1) ":") ((= e pows) "") (t ","))))
(html:th
(lambda () (fmt h e) p)
:nowrap t)))))
(loop for i from 1 to nums do
(html:lfd)
(html:tr
(lambda ()
(loop for e from 1 to pows do
(html:td
(lambda () (princ (expt i e) lhp-stream)))))
:align "right"))))
Notice how this also forces the optional "attributes" of any
HTML element into being *after* the closure which generates
the content of the element. Ugly. Error-prone.
No, I'll stick with "the macro style", thanks...
-Rob
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607