2011-04-12 68 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