Wann sollten scharfe Anführungszeichen verwendet werden?

9

Ich sehe scharfe Anführungszeichen im eLisp-Code anderer Leute, und ich benutze sie selbst, aber ich bin mir nicht ganz sicher, wann sie angemessen sind und wann nicht.

Könnte jemand genau klären, wann es angebracht ist, scharfe Anführungszeichen zu verwenden und wann stattdessen normale einfache Anführungszeichen verwendet werden sollten?

izkon
quelle
3
nb Es gibt viele Duplikate für diese Frage hier oder auf SO
Phils
Mögliches Duplikat von Wann soll ein Lambda-Ausdruck scharf zitiert werden?
Andrew Swann
1
Ich denke nicht, dass es sich um ein Duplikat handelt: Bei emacs.stackexchange.com/questions/3595 geht es um die Verwendung #'mit Lambda (wobei die Antwort im Grunde "nie" lautet), während die Frage von @ izkon eher für die Verwendung von #'Symbolen gilt.
Stefan

Antworten:

11

#'ist nur eine Abkürzung für function, genauso wie 'eine Abkürzung für quote.

Sie können es überall dort verwenden, wo Sie dem Byte-Compiler oder dem Interpreter oder einem menschlichen Leser anzeigen möchten, dass sein Argument eine Funktion sein soll (als solche behandelt wird).

In vielen Kontexten bestimmt der Kontext, wie das Argument behandelt wird, wenn Sie es beispielsweise einfach zitieren (verwenden quoteoder ') anstatt verwenden #'(oder function). In einem Kontext, in dem ein Symbol nur für seine symbol-functionEigenschaft verwendet wird, dh als Funktion verwendet wird, können Sie das Symbol einfach übergeben (z. B. durch Zitieren oder Übergeben einer Variablen, deren Wert das Symbol ist).

Aber manchmal ist Code klarer, wenn Sie ihn #'in solchen Kontexten verwenden. Selbst wenn Emacs-Lisp selbst versteht, dass das Symbol in solchen Kontexten als Funktion verwendet wird, kann es hilfreich sein, dies für einen menschlichen Leser des Codes hervorzuheben.

In einigen anderen Lisps kann die Behandlung von Lambda-Formen, die einfach (mit ') oder nicht zitiert werden, von ihrer Verwendung in einer Funktionsposition abweichen, wenn sie mit function( #') zitiert werden . Aber nicht in Emacs Lisp. In Emacs Lisp müssen Sie kein Lambda-Formular (mit 'oder #') zitieren , das als Funktion (und nicht nur als Liste) behandelt werden soll. Wenn Sie möchten, dass es nur als Liste, mit Auto lambdausw. behandelt wird, zitieren Sie es (mit ') - das folgende Beispiel veranschaulicht dies.

Von (elisp) anonymen Funktionen :

- Sonderformular: function function-object

Dieses spezielle Formular wird zurückgegeben, FUNCTION-OBJECTohne es auszuwerten.

In dieser quoteHinsicht ähnelt es (* note Quoting: :). Im Gegensatz quotedazu dient es aber auch als Hinweis für den Emacs-Evaluator und Byte-Compiler, FUNCTION-OBJECTder als Funktion verwendet werden soll. Angenommen, es FUNCTION-OBJECThandelt sich um einen gültigen Lambda-Ausdruck, hat dies zwei Auswirkungen:

• Wenn der Code bytekompiliert ist, FUNCTION-OBJECTwird er in ein Bytecode-Funktionsobjekt kompiliert (* Hinweis Byte-Kompilierung: :).

• Wenn die lexikalische Bindung aktiviert ist, FUNCTION-OBJECTwird sie in einen Abschluss umgewandelt. * Hinweis Verschlüsse ::.

Die Lesesyntax #'ist eine Abkürzung für die Verwendung function. Die folgenden Formen sind alle gleichwertig:

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

Im folgenden Beispiel definieren wir eine change-propertyFunktion, die eine Funktion als drittes Argument verwendet, gefolgt von einer double-property Funktion, die change-propertyeine anonyme Funktion übergibt:

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

Beachten Sie, dass wir das lambdaFormular nicht zitieren .

Wenn Sie den obigen Code kompilieren, wird auch die anonyme Funktion kompiliert. Dies würde nicht passieren, wenn Sie beispielsweise die anonyme Funktion durch Zitieren als Liste erstellt hätten:

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

In diesem Fall wird die anonyme Funktion als Lambda-Ausdruck im kompilierten Code beibehalten. Der Byte-Compiler kann nicht davon ausgehen, dass diese Liste eine Funktion ist, obwohl sie wie eine aussieht, da er nicht weiß, dass change-propertyer sie als Funktion verwenden möchte .

Drew
quelle
9

#'(aka function) kann vor verwendet werden, ist dort (lambda ...)jedoch überflüssig. Der einzige Ort, an dem es wirklich sinnvoll ist, befindet sich vor einem Symbol, wie in #'car. In elisp, #'carund 'carfast völlig gleichwertig sind, so eine der Hauptzweck einfach ist die Absicht zu dokumentieren (dh , um anzuzeigen , wer auch immer diesen Code liest , dass Sie dieses Symbol als eine Funktion verwenden möchten). Es gibt jedoch einige Umstände, unter denen der Unterschied bedeutender ist:

  • Der Byte-Compiler nutzt diese dokumentierte Absicht und #'carprüft beim Schreiben , ob sie carals Funktion vorhanden ist. Wenn er sie nicht findet, gibt er eine Warnung aus, genau wie bei einem Aufruf dieser Funktion .
  • Innerhalb cl-fletund cl-labelskann nur #'fauf die lokal definierte Funktion verweisen f, da 'fimmer noch auf das globale Symbol verwiesen wird f(und welche Funktion auch immer in seinem symbol-functionSteckplatz gespeichert sein mag ). Z.B

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