Ich habe das Folgende:
(setq some-variable "less")
Ich bin verwirrt, warum ich das einfache Anführungszeichen mit verwenden muss, boundp
aber nicht mit bound-and-true-p
.
Beispiel 1:
(when (boundp 'some-variable)
(message "some-variable is %s" some-variable))
Ergebnis:
"eine Variable ist weniger"
Beispiel 2a:
(when (bound-and-true-p some-variable) ;; Note that using single-quote causes error
(message "some-variable is %s" some-variable))
Ergebnis:
"eine Variable ist weniger"
Beispiel 2b:
(when (bound-and-true-p 'some-variable) ;; Note that using single-quote causes error
(message "some-variable is %s" some-variable))
Ergebnis:
und: Falsches Typargument: symbolp, (zitiere eine Variable)
setq
stehtset quoted
und ursprünglich ein Makro, das erweitert wurde(set 'some-variable "less")
. Im Allgemeinen ist Elisp in Bezug auf Argumente in Anführungszeichen und nicht in Anführungszeichen nicht besonders konsistent, aber jede Funktion (kein Makro), die mit einer Variablen anstelle eines Werts interagieren muss, verwendet ihr Argument in Anführungszeichen (setq
eine wichtige Ausnahme).bound-and-true-p
ist ein dummes Makro. Oder besser gesagt, sein Name ist dumm. 99,99% der Zeit , wenn Sie wollen, tun(and (boundp 'FOO) FOO)
Sie es tun , um den Wert zu verwendenFOO
. Sie tun es nicht nur, um einen Wahrheitswert zu erhalten. (1) Das Makro wird nicht benötigt - der Code, den es ersetzt, ist trivial und klein. (2) Der Name ist irreführend - es geht um den Variablenwert, nicht nur darum zu testen, ob der Variablenwert ist oder nichtnil
.Antworten:
Kurze Antwort
Wenn Sie versuchen, die Variable selbst zu verwenden, verwenden Sie
'some-variable
. Wenn Sie versuchen, den in der Variablen gespeicherten Wert zu verwenden, verwenden Siesome-variable
.Erläuterung
Informationen zur manuellen Definition finden Sie im Handbuch .
'
und(quote ...)
beide führen in emacs-lisp den gleichen zweck aus.Ziel ist es, das nicht bewertete Formular an die Umgebung weiterzugeben, anstatt es zu bewerten.
Nehmen wir in Ihrem Beispiel an, wir hätten das Folgende oben
Dann läuft die Auswertung wie folgt ab:
Während ohne ein Zitat:
Lisp wertet Formulare so aus, wie sie erreicht sind, indem Sie das Formular, das Sie nicht auswerten möchten, in Anführungszeichen setzen, damit die tatsächliche Variable (oder Liste oder Funktionsname) übergeben wird.
quelle
bound-and-truep
und die Frage war, warum ich bei der Verwendung zitieren muss,boundp
aber nicht bei der Verwendungbound-and-truep
.boundp
Erfordernis eines Symbols (nicht bewertet) undbound-and-truep
dem Erfordernis des Werts der Variablen in den Aufzählungspunkten (bearbeitet nach der ersten Antwort) einEin nicht funktionsfähiges Symbol wird als Name einer Variablen behandelt. In
(function variable)
function
ist in Funktionsposition (nach der öffnenden Klammer) undvariable
nicht. Sofern nicht explizit angegeben, werden Variablen durch ihre Werte ersetzt.Wenn Sie schreiben
(boundp my-variable)
würden, würde dies bedeuten , dass "das Symbol ist, das im Wert der als Variablemy-variable
gebundenen Variablen gespeichert ist" und nicht "dasmy-variable
als Variable gebundene Symbol .Warum verhält es
bound-and-truep
sich also anders?Dies ist ein Makro und die normalen (Funktions-) Bewertungsregeln gelten hier nicht. Makros können frei entscheiden, ob und wann ihre Argumente bewertet werden. Tatsächlich transformieren Makros die Argumente auf irgendeine Weise und geben das Ergebnis als Liste zurück, die dann ausgewertet wird. Die Transformation und die endgültige Auswertung erfolgen zu unterschiedlichen Zeiten, die als Makroexpansionszeit und Auswertungszeit bezeichnet werden.
So
bound-and-true-p
sieht die Definition von aus:Dies verwendet Reader-Makros, die sich von Lisp-Makros unterscheiden (mehr dazu weiter unten). Um dies nicht weiter zu erschweren, verwenden Sie keine Reader-Makros:
Wenn du schreibst
das wird erstmal "übersetzt" nach
und dann wird das als Rückgabe gewertet,
nil
wennmy-variable
nichtboundp
oder sonst der Wert vonmy-variable
(was natürlich auch sein kannnil
).Sie haben vielleicht bemerkt, dass die Erweiterung nicht war
wie wir es erwartet hätten.
quote
ist eine spezielle Form, kein Makro oder eine Funktion. Sonderformen können wie Makros mit ihren Argumenten alles machen. Diese spezielle Form gibt einfach ihr Argument, hier ein Symbol, anstelle des variablen Wertes des Symbols zurück. Das ist eigentlich der einzige Zweck dieses speziellen Formulars: die Verhinderung der Auswertung! Makros können das nicht alleine, sie müssen es benutzenquote
.Also, was ist
'
los mit ? Es ist ein Reader-Makro , das, wie oben erwähnt, nicht mit einem Lisp-Makro identisch ist . Während Makros zum Transformieren von Code / Daten verwendet werden, werden Lesemakros früher beim Lesen von Text verwendet, um diesen Text in Code / Daten zu transformieren.ist eine Kurzform für
`
In der eigentlichen Definition von wirdbound-and-true-p
auch ein Reader-Makro verwendet. Wenn ein Symbol in Anführungszeichen gesetzt wird`symbol
, ist dies äquivalent zu'symbol
, aber wenn eine Liste in Anführungszeichen gesetzt wird`(foo bar ,baz)
, verhält es sich anders, als wenn Formulare, denen ein Präfix vorangestellt,
ist, ausgewertet werden.ist äquivalent zu
Dies sollte die Frage beantworten, warum nicht zitierte Symbole manchmal ausgewertet werden (durch ihre Werte ersetzt werden) und manchmal nicht. Mit Makros kann
quote
verhindert werden, dass ein Symbol ausgewertet wird.Aber warum ist
bound-and-true-p
ein Makro, währendboundp
es nicht ist? Wir müssen feststellen können, ob beliebige Symbole, die erst zur Laufzeit bekannt sind, als Symbole gebunden sind. Dies wäre nicht möglich, wenn dasboundp
Argument automatisch in Anführungszeichen gesetzt würde.bound-and-true-p
wird verwendet, um zu bestimmen, ob eine bekannte Variable definiert ist, und wenn ja, ihren Wert zu verwenden. Dies ist nützlich, wenn eine Bibliothek eine optionale Abhängigkeit von einer Drittanbieter-Bibliothek aufweist, wie in:bound-and-true-p
kann als Funktion definiert werden und erfordert die Angabe des Arguments in Anführungszeichen, da dies jedoch für Fälle gedacht ist, in denen Sie im Voraus wissen, welche Variable Sie für ein Makro verwenden, um zu vermeiden, dass Sie das eintippen müssen'
.quelle
Aus dem Quellcode von
boundp
:boundp
erwartet asymbol
als eingabe.'some-variable
ist ein Symbol für die Variablesome-variable
.Aus dem Quellcode von
bound-and-true-p
:bound-and-true-p
erwartet avariable
als eingabe.Innerhalb des
bound-and-true-p
Makros erhält es das Symbol, indem es tut(quote ,var)
. Also, wenn die Eingabe istsome-variable
,(quote ,var)
wird sich ergeben'some-variable
.Aber wenn ich den Eingang geben
'some-variable
anbound-and-true-p
, erhalte ich die Fehlermeldung:and: Wrong type argument: symbolp, (quote some-variable)
da das Makro ein Symbol nicht erwartet ('some-variable
) am Eingang.quelle
''symbol
macht Sinn. Es bedeutet(quote (quote symbol))
. Der Grund, warum Sie eine Fehlermeldung erhalten, ist, dass dies kein gültiges Argument für istboundp
.