【问题标题】:Backquote String Interpolation反引号字符串插值
【发布时间】:2015-06-12 16:15:11
【问题描述】:

可以用lisp的宏做字符串插值吗?

例如,我可以做一个这样的宏吗:

(defmacro test (a) `",a")

所以 (test abc) 将 "abc" 作为字符串返回?我可能会通过引用它并将该引用转换为字符串来作弊,但这不适用于像“9:00”这样的参数(没有双引号)。

【问题讨论】:

  • 试试(symbol-name 'a)
  • @Dan:这不适用于我的示例。 '9:00 尝试查找名为“9”的包,但该包不存在。
  • @iHuman 你需要逃避它。例如。 '9\:00'|9:00|.

标签: macros lisp common-lisp


【解决方案1】:

Lisp 宏对已被 lisp 阅读器读取的参数进行操作。因此,宏无法更改其参数的读取方式,并且如果您传递的参数会在您尝试读取它时发出错误信号,例如9:00(test 9:00) 中,阅读器在宏开始运行之前发出错误信号。

阅读器也是可定制的。不是让您以直接的方式将9:00 读取为"9:00",但例如您可以编写一个简短的读取器宏,将@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")

【讨论】:

  • 谢谢。我试图跳过箍以使其成为字符串的原因是因为我在命令行参数的连接版本上使用了 read-from-string。这导致使用双引号很痛苦,因为 bash 没有将引号传递给 lisp。 '@' 在 bash 中没有什么特别之处,所以我会按照你的想法来。
  • @iHuman 我添加了一个简单的例子。在新的 readtable(使用 copy-readtable 创建)中设置 reader 宏并在本地绑定 *readtable* 可以防止更改在遥远的代码中产生意外影响。
  • 如果您只想以结构化的形式获取命令行参数,请查看所有的命令行解析器(或直接使用它们)。
【解决方案2】:

反引用,无论是否在宏中,都不会这样做:

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

【讨论】:

  • 所以我必须使用字符串?
  • 对于9:00,是的,你会的。对于其他一些符号,您不必这样做,但对此类数据使用字符串通常是一个好主意。请参阅 m-n 的回复以更好地解释为什么会这样。
  • 您的问题是“是否可以使用 lisp 的宏进行字符串插值?”是的,您必须使用字符串进行字符串插值。如果幻想语法",a" 有效,那将是一种字符串操作形式。
【解决方案3】:

有关字符串插值,请参阅format。例如。 (format nil "~a" a) 做你想做的事。在Practical Common Lisp 中有一些format recipes

quasiquote 和 unquote 仅适用于列表,不适用于其他序列。

宏是代码的转换。它不是在运行时发生的。例如。当你有像(my-macro x) 这样的代码,其中x 在运行时是一个字符串,宏只会看到这个符号。它在扩展时无法知道它是什么类型。

【讨论】:

    猜你喜欢
    • 2015-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-13
    • 2011-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多