【问题标题】:Read input into string in Lisp reader macro在 Lisp 阅读器宏中将输入读入字符串
【发布时间】:2015-06-19 16:20:14
【问题描述】:

我正在尝试制作一个可以将@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) 尝试过,但这只是返回变量 test,它没有被设置。我不能硬编码@符号后的字符数,因为我不知道会有多少。有没有办法解决这个问题?

编辑:是循环读取字符和窥视字符的唯一方法,一直读取到 #)、#\space 或 #\Newline?

【问题讨论】:

    标签: macros common-lisp reader-macro


    【解决方案1】:

    你可以尝试使用read,然后看看它返回了什么:

    (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"
    

    【讨论】:

    • 是否可以允许它包含数字和冒号?
    • @iHuman 第二个版本接受任何东西.. 例如@;test => ";test".
    猜你喜欢
    • 2014-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-31
    • 2015-07-09
    相关资源
    最近更新 更多