2011-04-12 69 views
0

我正在创建一个领域特定的语言。其中一个宏调用看起来是这样的:我可以区分字符串文字参数和计算为字符串的参数吗?

(我的宏了foo(bar“巴兹” qux)耶)

随着我已经写了我的宏的方式,这里的第二个参数应该是一对括号内的字符串列表。因此,只要bar和qux评估字符串,我的宏就可以工作。让我们只是说他们评价为“bar”和“qux”,my-macro将第二个参数视为“bar baz qux”。

但是现在我意识到我真的想要“baz”保留它的引号;我希望我的宏将第二个参数视为“bar \”baz \“qux”。这可能吗?在我的宏里面,我可以告诉我什么时候可以直接使用字符串,而当我需要添加双引号时?

在此先感谢!

回答

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)

+0

@泰耶 - norderhaug唉我想酒吧和qux评估和‘巴兹’仍然是一个带引号的字符串。另外一个引用的字符串可以出现在arg2中的任何地方... – nil 2011-04-13 15:36:56

1

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

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

+0

但我错误地看着它: (defmacro我的宏(ARG) “(如果(stringp,ARG) (格式无 “\” 〜一\ “”,ARG) (格式无“〜一”,ARG))) (我的宏 “巴兹”) => “\” 巴兹\ “” \t \t(macroexpand“(我的宏evals到一个字符串)) =>“ \“一个字符串\”“ 我希望第二个评估为”一个字符串“ – nil 2011-04-13 14:35:12

+1

不要返回执行stringp检查的代码,直接执行stringp检查。 (defmacro my-macro(arg)(if(stringp arg)arg ...)) – Xach 2011-04-13 20:23:26

+0

谢谢!你的知足是通过我的头骨得到的。 – nil 2011-05-04 19:22:35

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"

请注意,如果参数isn “T字符串,该宏扩展为一种形式:

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

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

+0

@ terje-norderhaug - 感谢您的帮助! – nil 2011-05-04 19:23:05