я могу различить строковый литерал аргумента и параметр, который оценивается в строку? - PullRequest
0 голосов
/ 12 апреля 2011

Я создаю предметно-ориентированный язык. Один из вызовов макросов выглядит примерно так:

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

С учетом того, как я написал my-macro, второй аргумент здесь должен быть списком строк внутри пары скобок. Так что my-macro работает до тех пор, пока bar и qux вычисляются как строки. Скажем так, они однозначно оценивают «bar» и «qux», а my-macro обрабатывает второй аргумент как «bar baz qux».

Но теперь я понял, что действительно хочу, чтобы "баз" сохранил свои кавычки; Я хочу, чтобы мой макрос обрабатывал второй аргумент как "bar \" baz \ "qux". Это возможно? В моем макросе я могу сказать, когда я могу просто использовать строку «как есть» и когда мне нужно добавить двойные кавычки?

Заранее спасибо!

Ответы [ 3 ]

1 голос
/ 12 апреля 2011

Вашему макросу передаются символ FOO, список (BAR "baz" QUX) и символ YAY в качестве аргументов.Если вы хотите увидеть, является ли какой-либо из элементов во втором аргументе строкой, используйте для определения аргумента что-то вроде stringp в определении макроса.

Ваш макрос полностью контролирует, как работает оценка в результирующем расширении макроса,Он видит все свои аргументы без оценки.Если вы хотите узнать что-то о не оцененном коде, переданном в качестве аргументов, просто посмотрите на него.

0 голосов
/ 14 апреля 2011

Макрос может проверять тип своих аргументов во время раскрытия. Например, этот макрос будет создавать другой код в зависимости от того, является ли аргумент строкой или нет:

(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)

0 голосов
/ 12 апреля 2011

Для обработки второго аргумента как строки "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)

...