Wie können die Variablen ausgewertet werden, bevor sie einer Liste hinzugefügt werden?


30

Das Folgende funktioniert offensichtlich nicht und daher diese Frage.

Wie korrigiere ich den folgenden Code, damit der Wert von somelistwird '(("abc" . 123))?

(setq x "abc")
(setq y 123)
(setq somelist nil)
(add-to-list 'somelist '(x . y))

5
Haben Sie versucht, Quasiquoting? Versuchen Sie es `(,x . ,y).
Dan

Ah, das habe ich verpasst. Ich wusste nicht, wonach ich googeln sollte :). Ich habe versucht, (add-to-list 'somelist '(,x . ,y))aber das Backquote vergessen.
Kaushal Modi

Fragen, die als Duplikate dieser Frage angesehen werden, tauchen sehr oft auf. Kann jemand einen Weg finden, um Anfängern klarer zu machen, dass diese Frage / Antwort das ist, wonach sie suchen? Ich vermute, dass ein Teil des Problems darin besteht, dass der Titel dieser Frage nur Sinn macht, wenn Sie die eigentliche Ursache des Problems bereits kennen (dh Sie kennen die Antwort). Ich versuche mich als Benutzer vorzustellen, der keine Ahnung hat, dass Variablen ausgewertet werden müssen, und noch weniger, was das "Zitat" bedeutet, aber leer ausgeht. @Drew?
Stefan

@stefan: Anders als bei einer Fehlermeldung (die im Fragentitel einer Community-Frage + Antwort verwendet werden kann) ist der Fehler, falls vorhanden, auf das Zitieren von etwas zurückzuführen, das ausgewertet werden muss (und dies ist ein besonderer Fall) Dies kann weit entfernt von der Site des Zitats liegen. Üblicherweise gibt es keinen (Emacs) Fehler - nur ein Verhalten, das nicht dem entspricht, was der Benutzer wollte.
Drew

@Stefan: Mir fällt dafür kein großer Fragentitel ein. Aber wir könnten zumindest eine Frage formulieren, die sich direkt damit befasst, einschließlich eines "normalen" Falls, bei dem nur ein Anführungszeichen entfernt werden muss, und eines Falls, bei dem Quasiquotierung erforderlich ist. Eine gute Frage, die solche Fälle abdeckt, und eine gute Antwort, die sie abdeckt, wäre hilfreich. Was das Auffinden von Qs angeht, die Duplikate sind: Ohne eine Fehlermeldung im Q-Titel muss die gesamte Frage gelesen werden, und es muss bekannt sein, wie das Duplikat zu finden ist, auf das verwiesen werden soll.
Drew

Antworten:


30

Das allgemeine Problem besteht darin, dass Sie eine Evaluierung benötigen xund durchführen ymüssen, bevor sie eingefügt werden somelist. Das Problem mit der zitierten Liste (mit 'als Lesersyntax) ist, dass quotees sich um eine spezielle Form handelt, die ihr Argument nicht bewertet. Nach dem Docstring:

(quote ARG)

Gibt das Argument zurück, ohne es auszuwerten. (quote x)Ausbeuten x. Warnung: erstellt quotekeinen Rückgabewert, sondern gibt nur den Wert zurück, der vom Lisp-Reader vorkonstruiert wurde ...

Daher müssen Sie entweder ein Backquoting durchführen oder eine Funktion verwenden, die die Argumente bewertet.

Mit Backquoting können Sie Elemente einer Backquoting-Liste selektiv mit der folgenden ,Syntax auswerten :

(setq x "x-val" y "y-val" z "z-val" somelist nil)
'(x  y z)                            ; => (x y z)
`(x ,y z)                            ; => (x "y-val" z)
(add-to-list 'somelist `(x y ,z))    ; => ((x y "z-val"))

Alternativ können Sie cons(wie @tarsius in seiner Antwort vorschlägt) oder für eine beliebige Anzahl von Elementen Folgendes verwenden list:

(add-to-list 'somelist (cons x y))   ; => (("x-val" . "y-val"))
(setq somelist nil)                  ; reset
(add-to-list 'somelist (list x y z)) ; => (("x-val" "y-val" "z-val"))

Welche zu verwenden ist, hängt davon ab, was Sie mit den Elementen tun müssen.


19

Anführungszeichen nicht setzen, da Anführungszeichen nicht ausgewertet werden. Genau deshalb zitiert man - um eine Bewertung zu verhindern. Aber das ist nicht was du willst, also tu es nicht.

Verwenden Sie stattdessen das Formular, das eine Cons-Zelle aus zwei ausgewerteten Werten, ihren Argumenten, erstellt.

(cons x y)

Natürlich kann man auch Quasiquote machen, aber das ergibt hier keinen Sinn und sieht schlimmer aus. Verwenden Sie `und nur, ,wenn dies die Lesbarkeit verbessert, dh wenn Sie etwas Komplexeres tun, als eine Cons-Zelle zu konstruieren oder ein Atom oder eine Liste am Anfang einer vorhandenen Liste hinzuzufügen.

Mit Quasiquoting würde es so aussehen:

`(,x . ,y)

Das ist schlimmer, weil es zusätzliche Syntax verwendet, die in diesem Fall überhaupt nicht erforderlich ist und die verwendete Syntax verschleiert cons.


3
Guter Punkt auf consing. Bei Quasiquoting geht es mir eher um eine feinkörnige Kontrolle des Listeninhalts als um Lesbarkeit, aber ich stimme zu, dass der Anwendungsfall Sinn macht cons.
Dan

Vielen Dank für Ihre Antwort. Das war ein toller Moment für mich. Ich habe blindlings Anführungszeichen vor Listen und Nachteile gesetzt.
Kaushal Modi

@ Dan, na ja - und nein. Quasiquoting kann nichts tun , dass Sie nicht mit nur tun konnte cons, listund nconc. Außer schöner zu sein. Es ist syntaktischer Zucker, der nützlich ist, wenn Sie eine "feinkörnige Kontrolle des Listeninhalts" benötigen (wie bei "etwas Komplexeres tun, als ein Atom oder eine Liste am Anfang hinzuzufügen"). Und der zusätzliche Vorteil der Verwendung dieses syntaktischen Zuckers ist: Lesbarkeit. Quasiquoting bietet Ihnen keine zusätzliche feinkörnigere Kontrolle - es ermöglicht Ihnen lediglich, dasselbe mit weniger Fehlern beim ersten Versuch zu tun. :-)
tarsius
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.