将输入读入 Lisp reader 宏中的字符串
Read input into string in Lisp reader macro
我正在尝试制作一个 reader 宏,将 @this 转换为 "this"。
这是我目前拥有的:
(defun string-reader (stream char)
(declare (ignore char))
(format nil "\"~a\"" (read-line stream t nil t))
)
(set-macro-character #\@ #'string-reader )
问题是这需要我在 @this 之后放一个换行符。我也用 (read) 尝试过,但只是 returns 尚未设置的变量测试。我不能只是硬编码 @ 符号后的字符数,因为我不知道会有多少。有什么办法可以解决这个问题吗?
编辑:这是循环读取字符和查看字符的唯一方法,一直读取直到到达#)、#\space 或#\Newline?
你可以试试用read
然后看看是什么returns:
(defun string-reader (stream char)
(declare (ignore char))
(let ((this (let ((*readtable* (copy-readtable)))
(setf (readtable-case *readtable*) :preserve)
(read stream t nil t))))
(etypecase this
(string this)
(symbol (symbol-name this)))))
(set-macro-character #\@ #'string-reader)
以上将允许 @This
和 @"This"
,但不允许 @333
。
此版本只读取字符串直到出现空格:
(defun read-as-string-until-whitespace (stream)
(with-output-to-string (out-stream)
(loop for next = (peek-char nil stream t nil t)
until (member next '(#\space #\newline #\tab))
do (write-char (read-char stream t nil t) out-stream))))
(defun string-reader (stream char)
(declare (ignore char))
(read-as-string-until-whitespace stream))
(set-macro-character #\@ #'string-reader)
示例:
CL-USER 21 > @this
"this"
CL-USER 22 > @42
"42"
CL-USER 23 > @FooBar
"FooBar"
我正在尝试制作一个 reader 宏,将 @this 转换为 "this"。 这是我目前拥有的:
(defun string-reader (stream char)
(declare (ignore char))
(format nil "\"~a\"" (read-line stream t nil t))
)
(set-macro-character #\@ #'string-reader )
问题是这需要我在 @this 之后放一个换行符。我也用 (read) 尝试过,但只是 returns 尚未设置的变量测试。我不能只是硬编码 @ 符号后的字符数,因为我不知道会有多少。有什么办法可以解决这个问题吗?
编辑:这是循环读取字符和查看字符的唯一方法,一直读取直到到达#)、#\space 或#\Newline?
你可以试试用read
然后看看是什么returns:
(defun string-reader (stream char)
(declare (ignore char))
(let ((this (let ((*readtable* (copy-readtable)))
(setf (readtable-case *readtable*) :preserve)
(read stream t nil t))))
(etypecase this
(string this)
(symbol (symbol-name this)))))
(set-macro-character #\@ #'string-reader)
以上将允许 @This
和 @"This"
,但不允许 @333
。
此版本只读取字符串直到出现空格:
(defun read-as-string-until-whitespace (stream)
(with-output-to-string (out-stream)
(loop for next = (peek-char nil stream t nil t)
until (member next '(#\space #\newline #\tab))
do (write-char (read-char stream t nil t) out-stream))))
(defun string-reader (stream char)
(declare (ignore char))
(read-as-string-until-whitespace stream))
(set-macro-character #\@ #'string-reader)
示例:
CL-USER 21 > @this
"this"
CL-USER 22 > @42
"42"
CL-USER 23 > @FooBar
"FooBar"