Подтвердить что ты не робот

Общий 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)

Итак:

  • Двойно-некотируемая форма полностью расширяется.
  • Одинаково-некотируемая форма не расширяется.
  • Необязательно с запятой, форма полностью расширяется и результат цитируется.
4b9b3361

Ответ 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"