[免责声明:我无法让CLSQL工作,而且无论如何都不想与数据库有任何关系,所以这个答案是关于其他事情的问题。]
我想你可能会对宏感到困惑,但你的
defpage
宏被混淆了。
CL-WHO的
with-html-output
做的就是
将流绑定到可以打印的变量
,然后将其主体视为它和所有类似的宏(我认为HTOUT是第一个真正做到这一点的宏)所理解的隐式“html-lisp”语言。这意味着,如果要将输出发送到此流,则需要将其打印到此流。
with-html-output-to-string
只是以显而易见的方式将输出捕获到字符串中。
以下是该宏的清理版本,名称更好(
defpage
闻起来像是“定义页面”(define page),而这根本不是它所做的)。
(defmacro with-output-to-standard-page ((&key (title "page")
(stream '*standard-output*)
(string-form 'nil))
&body content)
(let ((tv (make-symbol "TITLE")))
`(let ((,tv ,title))
(with-html-output-to-string (,var ,string-form :prologue t :indent t)
(:html
:xmlns "http://www.w3.org/1999/xhtml"
:xml\:lang "en"
:lang "en"
(:head
(:meta
:http-equiv "Content-Type"
:content "text/html;charset=utf-8")
(:title (princ ,tv ,var))
(:link :type "text/css"
:rel "stylesheet"
:href "/styles.css"))
(:body :class "whole-page"
(:div :class "site-articles"
(:div :class "article-body"
(:div :class "on-page-title"
(:h1 :class "main-header"
(princ ,tv ,var)))
,@content))))))))
这种行为比你的行为更传统:
(let ((title "foo"))
(with-output-to-standard-page (:title title)
...))
将起作用,并且
(with-output-to-standard-page (:title (complicated-function-with-state))
...)
将呼叫
complicated-function-with-state
只有一次。
此外,如果您需要,还可以定义流变量和字符串形式:
(with-output-to-standard-page (:var s)
(princ "foo" s))
将起作用。
最后,它将内容放在首字母下面
h1
,不在里面(和外面
on-page-title
div
事实上),并将标题用于
h1
。
所有这些都是在一个包中完成的,该包使用
CL-WHO
,
HUNCHENTOOT
和
BORDEAUX-THREADS
以避免可怕的包前缀everwhere恐怖,并使代码可读。
那么,如果我们更换
get-content
函数,因为没有SQL:
(defun get-content ()
(list 'nothing "my page content"))
然后,将处理程序更正为
打印
流,这是关键问题
(define-easy-handler (test-page :uri "/wow") ()
(let ((content-thread
(make-thread
(lambda ()
(second (get-content))))))
(with-output-to-standard-page (:var p :title "Main One")
(princ (join-thread content-thread) p))))
现在一切都会好起来的。
看着你
access-db
宏观方面,几乎可以肯定,它也存在问题。
首先,我称之为
with-db-access
因为
with-*
是这样的宏的一个常规名称(另一种可能是
accessing-db
)。然后,它至少有一个问题,那就是它将对第一个参数进行乘法运算。它应该是这样的
(defmacro with-db-access (db &body query)
(let ((dbv (make-symbol "DB")))
`(let ((,dbv ,db))
(connect ,dbv)
(unwind-protect
(progn ,@query)
(disconnect-db ,dbv)))))
以避免该问题。
请注意,使用Tim Bradshaw的
metatronic macros
。使用它,这将是:
(defmacro/m with-db-access (db &body query)
`(let ((<db> ,db))
(connect <db>)
(unwind-protect
(progn ,@query)
(disconnect-db <db>))))
我的
with-output-to-standard-page
上面的宏将使用metatronic宏进行类似的简化。