Общий Lisp Double-Backquote, Unquote, Quote, Unquote sequence?
Я читаю 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)
Итак:
- Двойно-некотируемая форма полностью расширяется.
- Одинаково-некотируемая форма не расширяется.
- Необязательно с запятой, форма полностью расширяется и результат цитируется.
Ответы
Ответ 1
При оценке двойной обратной кавычки сначала обрабатывается внутренняя обратная каскада, и результат представляет собой одиночную обратную форму. При оценке внутренней обратной структуры оцениваются только элементы, предшествующие двум запятым. Однако результат оценки этих дважды неупорядоченных элементов по-прежнему (по отдельности) неупорядочен и, таким образом, оценивается снова, когда оценивается одна обратная кадровая форма. Чтобы добиться оценки только во внутренней обращенной форме, необходимо ввести обычную цитату, в результате получив ,',
.
Посмотрите, как
(let ((tmp (gensym)))
``(lambda (,tmp ,,tmp ,',tmp) ()))
оценивается как
`(LAMBDA (,TMP ,#:G42 #:G42) nil)
Ответ 2
Символ "," X используется для защиты X от другой оценки.
Посмотрите, как:
(setq a 'fn)
(let ((x 'a)) ``(,,x ,',x)) ==> `(,a a) ==> (fn a)
;; ``,',X ==> `,(quote "the value of X") ==> "the value of X"
;; ``,,X ==> `,"the value of X" ==> "the value of the value of X"