started - ¿El significado de @(at-sign) en Lisp?
lisp getting started (3)
Todos conocen la historia: el programador lee el código de otras personas, el programador ve un símbolo que no entiende, Google falla porque es difícil buscar símbolos no alfanuméricos.
Esta vez es el símbolo @
, que parece ser usado para inyectar el contenido de una lista en el medio de otra. Por ejemplo:
`(5 6 7 ,@''(8 9) 10 11)
;=> (5 6 7 8 9 10 11)
Me siento cómodo con este uso, pero me pregunto si entiendo el comportamiento de @
correctamente. ¿Tiene otros usos? ¿Y qué causa el error en la siguiente transcripción (de CLISP)?
[1]> (list 1 2 3 4 @''(5 6 7))
*** - SYSTEM::READ-EVAL-PRINT: variable @ has no value
Por último, ¿qué es exactamente @
? No parece ser una función:
[3]> (print #''@)
*** - FUNCTION: undefined function @
Supongo que es una sintaxis fundamental como backquote ( `
), o coma ( ,
). ¿Es esto correcto? Lo siento si esto es un duplicado, pero una vez más, por lo que sé, es imposible buscar @
.
", @" Se usa para empalmar entre comillas traseras ...
Se describe en HyperSpec en la sección sobre backquote:
2.4.6 Backquote
Si una coma es seguida inmediatamente por un signo en, entonces la forma que sigue al signo en se evalúa para producir una lista de objetos. Estos objetos se "empalman" en su lugar en la plantilla. Por ejemplo, si
x
tiene el valor(abc)
, entonces
`(x ,x ,@x foo ,(cadr x) bar ,(cdr x) baz ,@(cdr x)) => (x (a b c) a b c foo b bar (b c) baz b c)
Vale la pena señalar que ,@
no siempre es necesario; Según la misma documentación:
En cualquier lugar se puede usar ", @", la sintaxis ",." Se puede usar en su lugar para indicar que está permitido operar de forma destructiva en la estructura de lista producida por el formulario que sigue a ",." (En efecto, para usar nconc en su lugar de añadir).
... pero "@" en sí mismo es solo otra letra ...
Su intuición es correcta en su mayoría cuando se pregunta , "así que básicamente @ no significa nada y el único operador real es, @?" @
se puede utilizar en otros lugares como una letra normal. Es por eso que obtiene el error que mencionó: (list 1 2 3 4 @''(5 6 7))
es simplemente
(list 1 2 3 4 @ ''(5 6 7))
y @
es una variable, pero no tiene un valor aquí. Compare eso con:
(let ((@ 4.5))
(list 1 2 3 4 @ ''(5 6 7)))
;=> (1 2 3 4 4.5 (5 6 7))
... que, desafortunadamente, puede ser difícil de buscar.
Lo siento si esto es un duplicado, pero una vez más, hasta donde sé, es imposible buscar "@".
La búsqueda de documentación sobre ciertos caracteres no alfanuméricos puede ser difícil, pero he encontrado algunas técnicas que pueden ayudar. Por ejemplo, si va a lispdoc.com, puede buscar una comma
, y los resultados allí lo llevarán a una cita atrás. (La búsqueda de un signo no ayudó, sin embargo.) Esa no es una solución perfecta, pero puede ayudar a veces.
Comma-at es para el empalme de listas en CL. Coloca el contenido de la lista en la expresión que lo contiene, eliminando los paréntesis más externos de la lista. El libro ahora disponible gratuitamente de Paul Graham "En Lisp" contiene muchos más detalles sobre él, si mi mente me funciona bien, y es una buena lectura de todos modos si desea aprender más sobre Lisp avanzado.
,@
debe considerar como una entidad única, y el significado de ,@
es que las siguientes expresiones se empalman en la lista actual entre comillas.
Por ejemplo no puedes usar
`,@x
porque la expresión casi entre comillas no es una lista y ,@
requiere que se empalme una lista. Del mismo modo (en mi lectura del estándar) no puedes usar
`(list ,@5)
porque 5
no es una lista (sin embargo, tanto SBCL como CLISP lo permiten y se expanden a (list . 5)
).
EDITAR
En realidad, el comportamiento de SBCL y CLISP es aceptable, pero también sería aceptable para una implementación compatible dar un error si ,@
se usa ,@
con un argumento que no está en la lista.
La sección 2.4.6 de CLHS última última expansión posible para `((,ab) ,c ,@d)
muestra que generar un error para una no-lista también podría ser aceptable.