macros lisp common-lisp

macros - Common Lisp Double-Backquote, Unquote, Quote, Unquote sequence?



common-lisp (2)

Durante la evaluación de una forma con doble comillas, la primera cita interna se maneja primero, y el resultado es una forma con una única referencia. Durante la evaluación de la forma interna entre comillas, solo se evalúan los elementos precedidos por dos comas. Sin embargo, el resultado de la evaluación de estos elementos doblemente sin comillas sigue siendo (solo) sin citar, y por lo tanto, se evalúan nuevamente cuando se evalúa la forma de comillas simples. Para lograr la evaluación solo en la forma de comillas invertidas internas, se debe insertar una cita ordinaria, lo que resulta en ,'', .

Ver cómo

(let ((tmp (gensym))) ``(lambda (,tmp ,,tmp ,'',tmp) ()))

evalúa a

`(LAMBDA (,TMP ,#:G42 #:G42) nil)

Estoy leyendo Let Over Lambda, que trata sobre la creación de macros con capas bastante profundas. Es fascinante y, en su mayor parte, logro mantenerme al día.

En el Capítulo 4, Hoyte implementa macros de lectura para las funciones de coincidencia y reemplazo de CL-PPCRE, de manera que puede hacer cosas como:

(#~m/(foo|bar)/d+/ "Some foo99") ; matches! (#~s/foo(/d+)/bar/1/, "Some foo99") ; "Some bar99

Para lograr esto, definimos una macro que utiliza el doble backquote, ya que en realidad es expandida por una macro envoltura, que necesita el valor entre comillas (devuelve un formulario lambda). Dentro de la lista de casi cotizaciones, hay un uso de la siguiente secuencia ,'',varname , que no puedo entender. ¿Qué hace la inicial ,'' hacer aquí?

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

En realidad, es probable que sea mejor que lo defmacro a algo que solo use defmacro , para mayor claridad si no ha leído el libro. str es un símbolo y args es una lista:

(defmacro pcre/match-lambda-form (args) "Expands to a lambda that applies CL-PPCRE:SCAN" ``(lambda (,'',str) (cl-ppcre:scan ,(car ,args) ,'',str)))

¿Son las citas básicamente una cita doble de las partes internas, de modo que el resultado se puede anular dos veces? ¿Poner efectivamente ''str en la forma expandida, en lugar de solo str ?

EDITAR | Gracias a Terje D. y algunos jugando en el REPL, esta es la situación:

(defvar a 42) (equal ``(,,a) ''(list 42)) ; T (equal ``(,a) ''(list a)) ; T (equal ``(,'',a) ''''(42)) ; T (equal ``(a) ''''(a)) ; T (obviously)

Asi que:

  • Sin cotización doble, la forma está totalmente expandida.
  • Sin cotización, la forma no se expande.
  • Sin comillas con una coma, el formulario se expande completamente y el resultado se cita.

El '','', X truco se usa para proteger la X de otra evaluación.

Ver cómo:

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