我可以区分字符串文字参数和计算字符串的参数吗?

时间:2011-04-12 18:31:36

标签: macros common-lisp argument-passing

我正在创建一个特定于域的语言。其中一个宏调用看起来像这样:

(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我需要添加双引号?

提前致谢!

3 个答案:

答案 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)