Elisp-Idiom verstehen (Boolesche Werte vs. zitierte Argumente)?

7

Ich habe einige grundlegende Fragen zu elisp.

Ich sehe oft so etwas

(search-forward "something" nil 'noerror)

Und manchmal sehe ich so etwas

(search-forward "something" nil :noerror)

Was ist der Unterschied und sollte ich eine Form der anderen vorziehen?

Soweit ich alles verstehe, wird die leere Liste in einem booleschen Kontext als wahr ausgewertet. Aber wie kommt das Folgende:

Wenn der Sucher "etwas" nicht im Puffer vorhanden ist, springt der Punkt zum Ende des Puffers, wenn 'noerrorer anstelle von verwendet wird t. Bei tVerwendung bleibt der Punkt dort, wo er ist.

Erster Fall:

(search-forward "something" nil 'noerror);; 1.Evaluate this

;; end of buffer 2.point jumps here

Zweiter Fall:

(search-forward "something" nil t);; 1.Evaluate this, 2. Point stays here

;; end of buffer
Clemera
quelle
1
FWIW: Wenn alle Nichtwerte nilvon der angegebenen Funktion gleich behandelt werden, übergebe ich in meinem Code ein Symbol mit demselben Namen oder ähnlich dem in der Funktionsbeschreibung verwendeten Parameternamen und normalerweise in Großbuchstaben. Dies dient mir als Erinnerung, wenn ich den Code lese. ZB (search-forward "abc" nil 'NOERROR). Dies ist am hilfreichsten für optionale Argumente, die selten verwendet werden.
Drew

Antworten:

12

Boolesche Werte in elisp funktionieren wie folgt:

  • nilund ()(die, wie Sie beobachtet haben, dasselbe sind) sind falsch
  • Absolut alles andere ist wahr.

Das tSymbol existiert als 'reiner' Wert von true (wenn die Verwendung eines anderen Werts keinen Vorteil bringt), aber die meisten Funktionen versuchen, etwas zurückzugeben, das ansonsten nützlich sein könnte, wann immer dies möglich ist.

Siehe auch C-hig (elisp) nil and t RET

Wenn es darum geht, Schlüsselwortargumente oder andere Symbole als Nicht- nilWert zu verwenden, wenn sich der Code nur um niloder Nicht- Wert kümmert nil, ist dies wirklich nur eine Frage der persönlichen Präferenz. Es gibt keinen Unterschied in Bezug auf die Ausführung.

Ich habe einmal dasselbe gefragt und wurde informiert, dass der Keyword-Argument-Ansatz eine allgemeinere Lisp-ish-Methode ist.

(Ich habe mich entschlossen, selbst Schlüsselwortargumente zu verwenden, teils zur Hervorhebung der Syntax, teils, weil sie dadurch besser von Variablen- und Funktionssymbolen unterschieden werden.)

In Bezug auf Ihrem spezifisches Beispiel die Funktion tut differenzierbare zwischen verschiedenem nicht - nilWert und das Verhalten von seiner docstring bedeckt ist:

Optionales drittes Argument, wenn t, bedeutet, wenn fehlgeschlagen, nur zurückgeben nil(kein Fehler). Wenn nicht nilund nicht t, gehen Sie zum Such- und Rückkehrlimit nil.

Im Allgemeinen werden Sie feststellen, dass sich Docstrings eher auf "non-nil" als auf "true" oder "t" beziehen. Wenn Sie "t" sehen, besteht eine faire Chance, dass es sich um einen Sonderfall handelt.

Phils
quelle
Danke, das hat es für mich geklärt! Also ist alles außer Null wahr, aber t als "rein" unterscheidet sich davon.
Clemera
2
Nun, es ist immer noch nur ein Symbol (wenn auch ein selbstzitierendes, wie es nilist). Mit "rein" meine ich nur, dass es speziell existiert , um ein Wert zu sein, der "wahr" bedeutet, denn manchmal ist es das, was Sie wollen. Andere Nichtwerte nilsind jedoch immer noch genauso "wahr" wie sie tsind.
Phils
14

Einige historische Hinweise sind fällig.

Emacs Lisp leiht viele Dinge von Common Lisp aus, aber die Ähnlichkeit ist nur oberflächentief. Das Doppelpunktsymbol in Common Lisp ist ein Namespace-Qualifikationsmerkmal. Kanonische Symbolnamen bestehen aus zwei Teilen: dem Namen des Pakets und dem Namen des Symbols in diesem Paket. Dies ist beispielsweise cl-user:aproposein im Paket definiertes Symbol cl-user. Es gibt auch ein spezielles Schlüsselwortpaket, das beim Start automatisch von Common Lisp importiert wird. Dieses Paket wird für die Kommunikation zwischen anderen Paketen verwendet (damit Pakete, die symbolische Informationen aneinander senden müssen, nicht darüber streiten, wer sie deklarieren muss). Wie Sie vielleicht erraten haben, werden Symbole in diesem Paket mit dem führenden Doppelpunkt geschrieben.

Emacs Lisp hat kein Konzept für Pakete, aber der Doppelpunkt ist insofern etwas Besonderes, als er den Leser anweist, den Ausdruck als selbstbewertendes Symbol zu interpretieren (dh es handelt sich um eine Variable, deren Wert diese Variable selbst ist). Es gibt mehrere solche integrierte Selbst-Auswertung Symbole: tund nilsind Beispiele , die ich über später schreiben werde.

Das Apostroph stammt ebenfalls aus Common Lisp, wo es sich um ein Standardlesemakro handelt (dh um einen Code, den der Lisp-Interpreter beim Einlesen der Programmquelle ausführt). Es wird wie folgt erweitert: 'x -> (quote x)Dabei (quote ...)handelt es sich um eine spezielle Form, die den Lisp-Interpreter daran hindert, den Inhalt des Ausdrucks im Inneren auszuwerten. Emacs Lisp verfügt über drei integrierte Lesermakros : ', `und #, aber Sie können keine eigenen hinzufügen. Die ersten beiden werden erweitert auf (quote ...), die zweite ermöglicht jedoch eine spezielle Syntax zum Erstellen des nicht bewerteten Ausdrucks. #wird zu (function ...)form erweitert , wodurch der Interpreter angewiesen wird, dass der Wert im Funktionsnamespace nachgeschlagen werden muss.

Symbole in Emacs Lisp müssen einen bestimmten Wert haben (ähnlich wie Variablen in anderen Sprachen), da es sich sonst um einen Fehler handelt. Sie können die Bewertung jedoch mithilfe des Angebotsformulars verhindern.

Schließlich ist der Unterschied zwischen:

(search-forward "something" nil 'noerror)

und

(search-forward "something" nil :noerror)

Haben Sie im ersten Fall search-forwardmit einem Symbol ohne Wert aufgerufen , für das nur der Name bekannt ist, und im zweiten Fall haben Sie diese Funktion mit einem Symbol aufgerufen, dessen Wert dieses Symbol selbst ist. Es kommt also vor, dass es dieser Funktion egal ist, welche Sie verwenden.


Typen sind ein wichtiges Programmierwerkzeug für die automatische Überprüfung von Programmen. Das Emacs Lisp-Typsystem ähnelt Common Lisp darin, dass sein universeller Typ (geschrieben als t) der Typ ist, von dem alle anderen Typen abgeleitet sind. Andererseits nilist der Typ, von dem kein Typ abgeleitet ist (das Komplement von t). Dies unterscheidet sich von vielen gängigen Programmiersprachen, die möglicherweise kein universelles Konzept oder einen bestimmten booleschen Typ haben.

Leider hat Emacs Lisp diesen Teil leider nicht genau aus Common Lisp kopiert, und die type-ofFunktion liefert verwirrende Ergebnisse für tund nil.

Emacs Lisp:

(type-of t) ; symbol

Common Lisp

(type-of t) ; BOOLEAN

Die Common Lisp-Erweiterung von Emacs Lisp hat eine Funktion, cl-typepdie jedoch zum Verständnis der Beziehung beitragen kann. So zum Beispiel

(cl-typep 'noerror t) ; t

dh was auch immer es 'noerrorist, ist vom Typ t.

wvxvw
quelle
Interessante zusätzliche Hintergrundinformationen, danke!
Clemera
Wunderbare Erklärung. Ich habe auch etwas über Common Lisp gelernt. Vielen Dank.
GSL