Quando utilizzare le virgolette?


10

Vedo le virgolette utilizzate nel codice eLisp di altre persone e le uso da solo, ma non sono del tutto chiaro su quando sono appropriate e quando no.

Qualcuno potrebbe chiarire esattamente quando è appropriato usare virgolette acute e quando invece dovrebbero essere usate le virgolette singole ordinarie?


3
nb Ci sono molti duplicati per questa domanda qui o su SO
phils


1
Non penso che sia un duplicato: emacs.stackexchange.com/questions/3595 riguarda l'utilizzo #'con lambda (dove la risposta è sostanzialmente "mai"), mentre la domanda di @ izkon si applica piuttosto all'utilizzo dei #'simboli applicati.
Stefan,

Risposte:


12

#'è solo una scorciatoia per function, proprio come 'è una scorciatoia per quote.

Puoi usarlo ovunque tu voglia indicare al compilatore di byte, all'interprete o ad un lettore umano che il suo argomento dovrebbe essere (viene trattato come) una funzione.

In molti contesti il ​​contesto determina come viene trattato l'argomento se, ad esempio, lo si cita semplicemente (usa quoteo ') invece di usare #'(o function). Ad esempio, in un contesto in cui un simbolo viene utilizzato solo per la sua symbol-functionproprietà, ovvero viene utilizzato come una funzione, è possibile passare semplicemente il simbolo (ad es. Citandolo o passando una variabile il cui valore è il simbolo).

Ma a volte il codice è più chiaro se lo si utilizza #'in tali contesti. Anche se Emacs-Lisp stesso comprende che il simbolo è usato come funzione in tali contesti, potrebbe aiutare a enfatizzarlo per un lettore umano del codice.

In alcune altre Lisps, il trattamento di forme lambda che sono semplicemente citate (con ') o non quotate possono differire dal loro uso in una posizione di funzione quando quotate using function( #'). Ma non in Emacs Lisp. In Emacs Lisp non è necessario citare (usando 'o #') un modulo lambda che si desidera venga trattato come una funzione (e non semplicemente come un elenco). Se lo vuoi come un semplice elenco, con auto lambdaecc., Quindi citalo (con ') - l'esempio che segue illustra questo.

Da (anisp) Funzioni anonime :

- Modulo speciale: function function-object

Questo modulo speciale restituisce FUNCTION-OBJECTsenza valutarlo.

In questo, è simile a quote(* note Quoting: :). Ma a differenza quote, funge anche da nota per il valutatore e il compilatore di byte Emacs che FUNCTION-OBJECTdeve essere utilizzato come funzione. Supponendo che FUNCTION-OBJECTsia una valida espressione lambda, ciò ha due effetti:

• Quando il codice viene FUNCTION-OBJECTcompilato in byte , viene compilato in un oggetto funzione byte-code (* note Compilazione byte: :).

• Quando il legame lessicale è abilitato, FUNCTION-OBJECTviene convertito in una chiusura. * Note chiusure ::.

La sintassi di lettura #'è una scorciatoia per l'utilizzo function. I seguenti moduli sono tutti equivalenti:

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

Nel seguente esempio, definiamo una change-propertyfunzione che accetta una funzione come terzo argomento, seguita da una double-property funzione che utilizza change-propertypassando una funzione anonima:

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

Si noti che non citiamo il lambdamodulo.

Se si compila il codice sopra, viene compilata anche la funzione anonima. Ciò non accadrebbe se, diciamo, avessi costruito la funzione anonima citandola come un elenco:

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

In tal caso, la funzione anonima viene mantenuta come espressione lambda nel codice compilato. Il compilatore di byte non può presumere che questo elenco sia una funzione, sebbene sembri uno, poiché non sa che change-propertyintende utilizzarlo come funzione.


9

#'(aka function) può essere utilizzato di fronte (lambda ...)ma è ridondante lì, quindi l'unico posto in cui è veramente significativo è di fronte a un simbolo, come in #'car. In ELisp, #'care 'carsono quasi del tutto equivalenti, quindi uno degli scopi principali è semplicemente quello di documentare l'intenzione (cioè di indicare a chi legge questo codice che si intende utilizzare questo simbolo come funzione). Tuttavia ci sono alcune circostanze, in cui la differenza è più significativa:

  • Il compilatore di byte sfrutta questa intenzione documentata e quando scrivi #'carcontrollerà se caresiste come funzione e, se non lo trova, emetterà un avviso, proprio come farebbe se avessi una chiamata a quella funzione .
  • All'interno cl-flete cl-labels, #'fpuò solo fare riferimento alla funzione definita localmente f, perché 'frimarrà comunque il simbolo globale f(e qualunque funzione possa essere memorizzata nel suo symbol-functionslot). Per esempio

    (cl-flet ((car (x y) (+ x y)))
      (list #'car 'car))
    =>
    ((closure nil (x y) (+ x y)) car)
    
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.