Я читаю Let Over Lambda, в котором рассказывается о довольно глубокой многослойной макросъемке. Это увлекательно, и я в основном справляюсь с этим.
В главе 4 Hoyte реализует макросы считывателя для CL-PPCRE для соответствия и замены функций, так что вы можете делать такие вещи, как:
(#~m/(foo|bar)\d+/ "Some foo99") ; matches!
(#~s/foo(\d+)/bar\1/, "Some foo99") ; "Some bar99
Чтобы достичь этого, мы определяем макрос, который использует double-backquote, так как он фактически расширяется макросом-оболочкой, которому требуется указанное значение (оно возвращает форму лямбда). Внутри квазициклированного списка используется некоторая последовательность ,',varname
, которую я не могу опустить. Что здесь делает начальная ,'
?
(defmacro! pcre/match-lambda-form (o!args)
"Expands to a lambda that applies CL-PPCRE:SCAN"
``(lambda (,',g!str)
(cl-ppcre:scan ,(car ,g!args)
,',g!str)))
На самом деле, вероятно, лучше, если я перейду на то, что использует только defmacro
, для ясности, если вы не читали книгу. str
- символ, а args
- список:
(defmacro pcre/match-lambda-form (args)
"Expands to a lambda that applies CL-PPCRE:SCAN"
``(lambda (,',str)
(cl-ppcre:scan ,(car ,args)
,',str)))
Являются ли кавычки в основном двойными кавычками внутренних частей, так что результат может быть дважды без кавычек? Эффективно помещая 'str
в расширенную форму, а не просто str
?
ИЗМЕНИТЬ | Благодаря Terje D., а некоторые играют в REPL, это в значительной степени ситуация:
(defvar a 42)
(equal ``(,,a) '(list 42)) ; T
(equal ``(,a) '(list a)) ; T
(equal ``(,',a) ''(42)) ; T
(equal ``(a) ''(a)) ; T (obviously)
Итак:
- Двойно-некотируемая форма полностью расширяется.
- Одинаково-некотируемая форма не расширяется.
- Необязательно с запятой, форма полностью расширяется и результат цитируется.