我正在创建一个特定于域的语言。其中一个宏调用看起来像这样:
(my-macro foo(bar“baz”qux)yay)
通过我编写my-macro的方式,这里的第二个参数应该是一对括号内的字符串列表。所以只要bar和qux评估为字符串,my-macro就可以工作。让我们说他们同心地评价“bar”和“qux”,my-macro将第二个参数视为“bar baz qux”。
但现在我意识到我真的希望“baz”保留其报价;我希望my-macro将第二个参数视为“bar \”baz \“qux”。这可能吗?在my-macro里面,我可以告诉我何时可以使用字符串as-is vs我需要添加双引号?
提前致谢!
答案 0 :(得分:1)
您的宏传递符号FOO,列表(BAR“baz”QUX)和符号YAY作为参数。如果要查看第二个参数中的任何元素是否为字符串,请在宏定义中使用stringp
之类的内容来测试参数。
您的宏完全控制评估在生成的宏展开中的工作方式。它看到它的所有参数都未被评估。如果你想了解一些关于作为参数传递的未评估代码的信息,那就看看吧。
答案 1 :(得分:0)
要将第二个参数视为字符串"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)
答案 2 :(得分:0)
宏可以在扩展时测试其参数的类型。例如,根据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)