反引号字符串插值
Backquote String Interpolation
是否可以使用lisp的宏来做字符串插值?
例如,我可以制作这样的宏吗:
(defmacro test (a) `",a")
那么 (test abc) returns "abc" 作为一个字符串?我可能会通过引用它并将该引号转换为字符串来作弊,但这不适用于像“9:00”这样的参数(没有双引号)。
有关字符串插值,请参阅 format
. eg. (format nil "~a" a)
does what you want. In Practical Common Lisp there are some format recipes
quasiquote 和 unquote 仅适用于列表,不适用于其他序列。
宏是代码的转换。这不是运行时发生的事情。例如。当你有像 (my-macro x)
这样的代码时,其中 x
在运行时将是一个字符串,宏只看到符号。它无法知道它在扩展时是什么类型。
反引号,无论是否在宏中,都不会这样做:
[1]> (defmacro test (a) `",a")
TEST
[2]> (test oh-no)
",a"
你可以做的就是使用format
,如下:
[3]> (defun interp (name) (format nil "Hi, my name is ~A" name))
INTERP
[4]> (interp "Steve")
"Hi, my name is Steve"
Lisp 宏对已经被 lisp reader 读取的参数进行操作。正因为如此,宏不能改变它的参数被读取的方式,如果你传递一个参数,当你试图读取它时,它会发出错误信号,例如9:00
在 (test 9:00)
中,reader 甚至在宏开始 运行 之前就发出错误信号 运行。
reader也是可以自定义的。不是让您以直接的方式将 9:00
读作 "9:00"
的方式,但是例如您可以编写一个简短的 reader 宏,将 @9:00
读作 "9:00"
或作为日期对象。
编辑:像这样:
(defvar *arguments-rt* (copy-readtable ()))
(defun timestring-reader (stream char &optional count)
(declare (ignore char count))
(with-output-to-string (s)
(loop repeat 4 do (write-char (read-char stream) s))))
(set-macro-character #\@ #'timestring-reader () *arguments-rt*)
(let ((*readtable* *arguments-rt*))
(let ((args "dinner @9:00"))
(with-input-from-string (stream args)
(loop for arg = (read stream () ())
while arg collect arg))))
-> (DINNER "9:00")
是否可以使用lisp的宏来做字符串插值?
例如,我可以制作这样的宏吗:
(defmacro test (a) `",a")
那么 (test abc) returns "abc" 作为一个字符串?我可能会通过引用它并将该引号转换为字符串来作弊,但这不适用于像“9:00”这样的参数(没有双引号)。
有关字符串插值,请参阅 format
. eg. (format nil "~a" a)
does what you want. In Practical Common Lisp there are some format recipes
quasiquote 和 unquote 仅适用于列表,不适用于其他序列。
宏是代码的转换。这不是运行时发生的事情。例如。当你有像 (my-macro x)
这样的代码时,其中 x
在运行时将是一个字符串,宏只看到符号。它无法知道它在扩展时是什么类型。
反引号,无论是否在宏中,都不会这样做:
[1]> (defmacro test (a) `",a")
TEST
[2]> (test oh-no)
",a"
你可以做的就是使用format
,如下:
[3]> (defun interp (name) (format nil "Hi, my name is ~A" name))
INTERP
[4]> (interp "Steve")
"Hi, my name is Steve"
Lisp 宏对已经被 lisp reader 读取的参数进行操作。正因为如此,宏不能改变它的参数被读取的方式,如果你传递一个参数,当你试图读取它时,它会发出错误信号,例如9:00
在 (test 9:00)
中,reader 甚至在宏开始 运行 之前就发出错误信号 运行。
reader也是可以自定义的。不是让您以直接的方式将 9:00
读作 "9:00"
的方式,但是例如您可以编写一个简短的 reader 宏,将 @9:00
读作 "9:00"
或作为日期对象。
编辑:像这样:
(defvar *arguments-rt* (copy-readtable ()))
(defun timestring-reader (stream char &optional count)
(declare (ignore char count))
(with-output-to-string (s)
(loop repeat 4 do (write-char (read-char stream) s))))
(set-macro-character #\@ #'timestring-reader () *arguments-rt*)
(let ((*readtable* *arguments-rt*))
(let ((args "dinner @9:00"))
(with-input-from-string (stream args)
(loop for arg = (read stream () ())
while arg collect arg))))
-> (DINNER "9:00")