gpt4 book ai didi

macros - 宏展开后的未定义函数

转载 作者:行者123 更新时间:2023-12-01 14:00:59 30 4
gpt4 key购买 nike

我正在学习 Common Lisp 并想玩 lisp 和网络开发。我当前的问题来自一个简单的想法,即遍历我想要包含的所有 javascript 文件。我使用 SBCL 和 Quicklisp 来快速启动。该问题可能与我正在使用的 cl-who 包有关。

所以我已经声明了我的包裹并开始这样:

(defpackage :0xcb0
(:use :cl :cl-who :hunchentoot :parenscript))
(in-package :0xcb0)

为了简单起见,我减少了我的问题函数。所以我有这个 page 函数:

(defun page (test)
(with-html-output-to-string
(*standard-output* nil :prologue nil :indent t)
(:script
(:script :type "text/javascript" :href test))))

这将产生所需的输出

*(0xcb0::page "foo")

<script>
<script type='text/javascript' href='foo'></script>
</script>

现在我已经创建了一个生成 :script 标签的宏。

(defmacro js-source-file (filename)
`(:script :type "text/javascript" :href ,filename)))

这按预期工作:

*(macroexpand-1 '(0XCB0::js-source-file "foo"))

(:SCRIPT :TYPE "text/javascript" :HREF "foo")

但是,如果我将其包含到我的 page 函数中:

(defun page (test)
(with-html-output-to-string
(*standard-output* nil :prologue nil :indent t)
(:script
(js-source-file "foo"))))

...在定义新的page 函数时,它会给我一个样式警告(undefined function: :SCRIPT)。此外,page 函数在执行时会产生此错误:

*(0xcb0::page "foo")

The function :SCRIPT is undefined.
[Condition of type UNDEFINED-FUNCTION]

为什么嵌入式宏 js-source-file 会按预期工作,因为它会产生所需的输出,但在另一个函数中调用时会失败?

附言我知道 Lisp 中的宏主题对于像我这样的初学者来说可能会让人筋疲力尽。但目前我无法理解这应该有效但无效的事实!

最佳答案

问题是宏按照从最外层到最内层的顺序展开有点违反直觉。例如:

(defmacro foobar (quux)
(format t "Foo: ~s~%" quux))

(defmacro do-twice (form)
`(progn
,form
,form))

(foobar (do-twice (format t "qwerty")))

输出将是

Foo: (DO-TWICE (FORMAT T "qwerty"))

foobar 从未见过 do-twice 的扩展。你可以通过在 foobar 中自己调用 macroexpand 来避免这个问题:

(defmacro foobar (quux)
(format t "Foo: ~s~%" (macroexpand quux)))

(foobar (do-twice (format t "qwerty")))
; => Foo: (PROGN (FORMAT T "qwerty") (FORMAT T "qwerty"))

由于您使用的是第三方宏,这可能不是一个好的解决方案。我认为最好的选择是在 js-source-file 中自己生成标记。我不熟悉 cl-who,但这似乎在我的快速测试中有效:

(defun js-source-file (filename stream)
(with-html-output (stream nil :prologue nil :indent t)
(:script :type "text/javascript" :href filename))))

(defun page (test)
(with-output-to-string (str)
(with-html-output (str nil :prologue nil :indent t)
(:script
(js-source-file test str)))))

关于macros - 宏展开后的未定义函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35102637/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com