【问题标题】:can I distinguish between a string literal argument and a parameter which evaluates to a string?我可以区分字符串文字参数和计算为字符串的参数吗?
【发布时间】:2011-04-12 18:31:35
【问题描述】:

我正在创建一种特定领域的语言。其中一个宏调用如下所示:

(my-macro foo (bar "baz" qux) 耶)

按照我编写 my-macro 的方式,这里的第二个参数应该是一对括号内的字符串列表。因此,只要 bar 和 qux 计算为字符串,my-macro 就可以工作。假设它们以“bar”和“qux”同名计算,而 my-macro 将第二个参数视为“bar baz qux”。

但现在我意识到我真的希望“baz”保留它的引号;我希望 my-macro 将第二个参数视为“bar \"baz\" qux”。这可能吗?在 my-macro 中,我可以知道什么时候可以按原样使用字符串,什么时候需要加回双引号?

提前致谢!

【问题讨论】:

    标签: macros common-lisp argument-passing


    【解决方案1】:

    您的宏被传递符号 FOO、列表 (BAR "baz" QUX) 和符号 YAY 作为参数。如果您想查看第二个参数中的任何元素是否为字符串,请在宏定义中使用 stringp 之类的内容来测试参数。

    您的宏完全控制在生成的宏展开中求值的工作方式。它认为它的所有论点都未经评估。如果您想了解作为参数传递的未评估代码的一些信息,只需查看它。

    【讨论】:

    • 但是我看错了: (defmacro my-macro (arg) '(if (stringp ,arg) (format nil "\"~a\"" ,arg) (format nil "~a" ,arg))) (my-macro "baz") => "\"baz\"" (macroexpand '(my-macro evals-to-a-string)) => "\"a string\ "" 我希望第二个评估为 "a string"
    • 不返回执行stringp检查的代码,直接做stringp检查。 (defmacro my-macro (arg) (if (stringp arg) arg ...))
    【解决方案2】:

    要将第二个参数视为字符串"bar \"baz\" qux",您可以简单地将其写入字符串,如下所示:

    (defmacro my-macro (arg1 (&rest arg2) arg3)
      (list arg1 (write-to-string arg2 :case :downcase) arg3)) 
    
    (macroexpand '(my-macro foo (bar "baz" qux) yay))
    

    => (FOO "(bar \"baz\" qux)" YAY)

    【讨论】:

    • @terje-norderhaug 唉,我希望 bar 和 qux 进行评估,并且 "baz" 保持引用字符串。带引号的字符串也可以出现在 arg2 内的任何位置...
    【解决方案3】:

    宏可以在扩展时测试其参数的类型。例如,此宏将根据 arg 是否为字符串来创建不同的代码:

    (defmacro my-macro (arg) 
      (if (stringp arg)
         (format nil "\"~a\"" arg)
         `(format nil "~a" ,arg)))
    

    测试:

    (my-macro "baz")
    

    => "\"baz\""

    (let ((evals-to-a-string "a string"))
      (my-macro evals-to-a-string))
    

    => "a string"

    请注意,如果参数不是字符串,则宏会展开为形式:

    (macroexpand '(my-macro evals-to-a-string))
    

    => (format nil "~a" evals-to-a-string)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-10
      • 1970-01-01
      • 1970-01-01
      • 2011-08-07
      • 2021-10-28
      • 2017-10-22
      • 1970-01-01
      相关资源
      最近更新 更多