¿Cuándo deben usarse las comillas?

9

Veo que se usan comillas nítidas en el código eLisp de otras personas, y las uso yo mismo, pero no tengo completamente claro cuándo son apropiadas y cuándo no.

¿Podría alguien aclarar exactamente cuándo es apropiado usar comillas definidas y cuándo se deben usar comillas simples ordinarias?

izkon
fuente
3
nb Hay muchos duplicados para esta pregunta aquí o en SO
phils
¿Posible duplicado de cuándo citar una expresión lambda?
Andrew Swann
1
No creo que sea un duplicado: emacs.stackexchange.com/questions/3595 se trata de usar #'con lambda (donde la respuesta es básicamente "nunca"), mientras que la pregunta de @ izkon se aplica más bien al uso de #'símbolos aplicados.
Stefan

Respuestas:

11

#'se acaba de taquigrafía para function, al igual que 'es la abreviatura de quote.

Puede usarlo en cualquier lugar donde desee indicar al compilador de bytes o al intérprete o un lector humano que se espera que su argumento sea (se trata como) una función.

En muchos contextos, el contexto determina cómo se trata el argumento si, por ejemplo, simplemente lo cita (use quoteo ') en lugar de usar #'(o function). Por ejemplo, en un contexto en el que un símbolo se usa solo para su symbol-functionpropiedad, es decir, se usa como una función, puede pasar el símbolo (por ejemplo, al citarlo o al pasar una variable cuyo valor es el símbolo).

Pero a veces el código es más claro si lo usa #'en tales contextos. Incluso si Emacs-Lisp mismo entiende que el símbolo se usa como una función en tales contextos, podría ayudar enfatizar esto para un lector humano del código.

En algunos otros Lisps, el tratamiento de formas lambda que simplemente se citan (con ') o no se pueden citar de su uso en una posición de función cuando se citan usando function( #'). Pero no en Emacs Lisp. En Emacs Lisp no necesita citar (usando uno 'o más #') un formulario lambda que desee que se trate como una función (y no simplemente como una lista). Si desea que se maneje solo como una lista, con automóvil lambda, etc., cítelo (con '); el siguiente ejemplo ilustra esto.

De (elisp) Funciones anónimas :

- Forma especial: function function-object

Este formulario especial regresa FUNCTION-OBJECTsin evaluarlo.

En esto, es similar a quote(* note Quoting: :). Pero a diferencia quote, también sirve como una nota para el evaluador de Emacs y el compilador de bytes que FUNCTION-OBJECTestá destinado a ser utilizado como una función. Suponiendo que FUNCTION-OBJECTes una expresión lambda válida, esto tiene dos efectos:

• Cuando el código se FUNCTION-OBJECTcompila en bytes , se compila en un objeto de función de código de bytes (* nota Compilación de bytes: :).

• Cuando el enlace léxico está habilitado, FUNCTION-OBJECTse convierte en un cierre. * Nota Cierres ::.

La sintaxis de lectura #'es una abreviatura para usar function. Las siguientes formas son todas equivalentes:

(lambda (x) (* x x))
(function (lambda (x) (* x x)))
#'(lambda (x) (* x x))

En el siguiente ejemplo, definimos una change-propertyfunción que toma una función como su tercer argumento, seguida de una double-property función que utiliza change-propertyal pasarle una función anónima:

(defun change-property (symbol prop function)
   (let ((value (get symbol prop)))
     (put symbol prop (funcall function value))))

(defun double-property (symbol prop)
   (change-property symbol prop (lambda (x) (* 2 x))))

Tenga en cuenta que no citamos el lambdaformulario.

Si compila el código anterior, la función anónima también se compila. Esto no sucedería si, por ejemplo, hubiera construido la función anónima citándola como una lista:

(defun double-property (symbol prop)
   (change-property symbol prop '(lambda (x) (* 2 x))))

En ese caso, la función anónima se mantiene como una expresión lambda en el código compilado. El compilador de bytes no puede asumir que esta lista es una función, aunque parezca una, ya que no sabe si change-propertytiene la intención de utilizarla como una función.

Dibujó
fuente
9

#'(aka function) se puede usar delante de, (lambda ...)pero es redundante allí, por lo que el único lugar donde es realmente significativo es delante de un símbolo, como en #'car. En ELisp, #'cary 'carson casi completamente equivalentes, entonces uno de los propósitos principales es simplemente documentar la intención (es decir, indicar a quien lea este código que tiene la intención de usar este símbolo como una función). Sin embargo, hay algunas circunstancias en las que la diferencia es más significativa:

  • El compilador de bytes aprovecha esta intención documentada y cuando la escriba #'carverificará si carexiste como función, y si no la encuentra, emitirá una advertencia, tal como lo haría si tuviera una llamada a esa función .
  • Dentro cl-flety cl-labelssolo #'fpuede referirse a la función definida localmente f, ya 'fque todavía se referirá al símbolo global f(y a cualquier función que pueda estar almacenada en su symbol-functionranura). P.ej

    (cl-flet ((car (x y) (+ x y)))
      (list #'car 'car))
    =>
    ((closure nil (x y) (+ x y)) car)
    
Stefan
fuente