Frage

es durch die wichtigsten Teile eines einleitenden Lisp Buch Nachdem ich konnte immer noch nicht verstehen, was die speziellen Operator (quote) (oder gleichwertig ') funktioniert, aber das hat alles über Lisp-Code, die ich je gesehen habe.

Was ist zu tun?

War es hilfreich?

Lösung

Kurze Antwort Bypass die Standardbewertungsregeln und tun nicht bewertet den Ausdruck (Symbol oder s-exp), vorbei entlang auf die Funktion genau wie eingegeben hat.

Lange Antwort: Die Standard-Auswertungsregel

Wenn eine reguläre Funktion (I dieser kommen werde später) aufgerufen wird, werden alle Argumente an sie übergeben werden ausgewertet. Dies bedeutet, dass Sie diese schreiben können:

(* (+ a 2)
   3)

Was wiederum (+ a 2) auswertet, von a und 2. Der Wert des Symbols a Auswertung wird in der aktuellen variablen verbindliches nachgeschlagen, und dann ersetzt. Say ist a zur Zeit gebunden auf den Wert 3:

(let ((a 3))
  (* (+ a 2)
     3))

Wir würden erhalten (+ 3 2), + wird dann aufgerufen auf 3 und 2 Nachgeben 5. Unsere ursprüngliche Form jetzt 15 (* 5 3) Nachgeben wird.

Erklären quote Already!

In Ordnung. Wie oben zu sehen ist, werden alle Argumente an eine Funktion ausgewertet, so dass, wenn Sie das passieren möchten Symbol a und nicht seinen Wert, die Sie nicht wollen, es zu bewerten. Lisp Symbole können sowohl als ihre Werte verdoppeln und Markierungen, wo Sie in anderen Sprachen haben Strings verwendet würden, wie Schlüssel Tabellen Hash.

Dies ist, wo quote kommt. Sagen Sie bitte Ressourcenzuweisungen aus einer Python-Anwendung dargestellt werden sollen, sondern vielmehr das Plotten in Lisp zu tun. Lassen Sie Ihren Python App so etwas tun:

print("'(")
while allocating:
    if random.random() > 0.5:
        print(f"(allocate {random.randint(0, 20)})")
    else:
        print(f"(free {random.randint(0, 20)})")
    ...
print(")")

Sie Ausgang geben wie folgt aussehen (leicht prettyfied):

'((allocate 3)
  (allocate 7)
  (free 14)
  (allocate 19)
  ...)

Denken Sie daran, was ich gesagt habe über quote ( „tick“), was die Standardregel nicht anwenden? Gut. Was es sonst passieren, dass die Werte von allocate und free nachgeschlagen, und wir wollen das nicht. In unserem Lisp, wollen wir tun:

(dolist (entry allocation-log)
  (case (first entry)
    (allocate (plot-allocation (second entry)))
    (free (plot-free (second entry)))))

Für die oben angegebenen Daten, die folgende Sequenz von Funktionsaufrufen gemacht worden wäre:

(plot-allocation 3)
(plot-allocation 7)
(plot-free 14)
(plot-allocation 19)

Aber was ist list?

Nun, manchmal Sie tun wollen die Argumente bewerten. Angenommen, Sie haben eine nette Funktion eine Nummer und einen String und Zurückgeben einer Liste der erhaltenen ... Dinge zu manipulieren. Lassen Sie uns einen Fehlstart machen:

(defun mess-with (number string)
  '(value-of-number (1+ number) something-with-string (length string)))

Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER (1+ NUMBER) SOMETHING-WITH-STRING (LENGTH STRING))

Hey! Das ist nicht das, was wir wollten. Wir wollen selektiv einige Argumente bewerten, und die andere als Symbole lassen. Versuchen # 2!

(defun mess-with (number string)
  (list 'value-of-number (1+ number) 'something-with-string (length string)))

Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER 21 SOMETHING-WITH-STRING 3)

Nicht nur quote, aber backquote

Viel besser! Nebenbei bemerkt, ist dieses Muster so häufig in (meist) Makros, dass es eine spezielle Syntax für genau das zu tun. Das Backquote:

(defun mess-with (number string)
  `(value-of-number ,(1+ number) something-with-string ,(length string)))

Es ist wie quote verwenden, aber mit der Option explizit einige Argumente zu bewerten, indem sie mit Komma vorangestellt. Das Ergebnis entspricht list verwenden, aber wenn Sie Code aus einem Makro erzeugen, sind Sie oft nur kleine Teile bewerten von dem Code zurückgegeben, so dass die Backquote ist besser geeignet. Für kürzere Listen list kann besser lesbar sein.

Hey, Sie vergessen Über quote!

Also, wo führt uns das? Ach ja, was macht quote eigentlich tun? Es gibt einfach ihr Argument (e) unbewertet! Denken Sie daran, was ich gesagt habe am Anfang zu regulären Funktionen? Es stellte sich heraus, dass einige Operatoren / Funktionen nicht brauchen , ihre Argumente zu bewerten. Wie IF - Sie würden der andere Zweig nicht wollen ausgewertet werden, wenn es nicht gemacht, nicht wahr? Sogenannte spezielle Operatoren , zusammen mit Makros, wie das funktioniert. Spezielle Operatoren sind auch das „Axiom“ der Sprache - minimaler Satz von Regeln - auf die Sie den Rest Lisp sie zusammen durch die Kombination von auf unterschiedliche Weise umsetzen können.

Zurück zum quote, aber:

Lisp> (quote spiffy-symbol)
SPIFFY-SYMBOL

Lisp> 'spiffy-symbol ; ' is just a shorthand ("reader macro"), as shown above
SPIFFY-SYMBOL

Vergleichen zu (auf Stahl-Bank-Common Lisp):

Lisp> spiffy-symbol
debugger invoked on a UNBOUND-VARIABLE in thread #<THREAD "initial thread" RUNNING   {A69F6A9}>:
  The variable SPIFFY-SYMBOL is unbound.

Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [ABORT] Exit debugger, returning to top level.

(SB-INT:SIMPLE-EVAL-IN-LEXENV SPIFFY-SYMBOL #<NULL-LEXENV>)
0] 

Weilgibt es keine spiffy-symbol im aktuellen Bereich!

Aufsummierungs

quote, backquote (mit Komma), und list sind nur einige der Werkzeuge, die Sie Listen erstellen können, die nicht nur Wertelisten sind, aber wie man so leicht gesehen kann (keine Notwendigkeit, eine struct zu definieren) verwendet werden, um Daten Strukturen!

Wenn Sie mehr erfahren möchten, empfehle ich Peter Seibel Buch für einen praktischen Ansatz rel="noreferrer"> Lisp zu lernen wenn Sie bereits in der Programmierung im Allgemeinen sind. Schließlich auf Ihrer Lisp Reise, werden Sie beginnen Pakete zu verwenden. Ron Garrets Der Führer des Idioten zu Common Lisp-Pakete geben Ihnen gute Erklärung von denen.

Happy Hacking!

Andere Tipps

Er sagt: „Sie mich nicht beurteilen“. Zum Beispiel, wenn Sie eine Liste als Daten und nicht als Code verwenden wollten, dann würden Sie ein Angebot vor sich ausdrückte. Zum Beispiel:

(print '(+ 3 4)) prints "(+ 3 4)", während (print (+ 3 4)) prints "7"

Andere Leute diese Frage vortrefflich beantwortet haben, und Matthias Benkard bringt eine hervorragende Warnung auf.

NICHT QUOTE NUTZEN Listen zu erstellen, die Sie später ÄNDERN WERDEN. Die Spezifikation ermöglicht es den Compiler zitiert Listen als Konstanten zu behandeln. Oft wird ein Compiler Konstanten optimiert, indem sie einen einzelnen Wert für sie im Speicher zu schaffen und dann verweisen, dass die einzelnen Wert aus allen Orten, an denen die Konstante angezeigt. Mit anderen Worten, es kann die Konstante wie eine anonyme globale Variable behandeln.

Dies kann offensichtlich Probleme verursachen. Wenn Sie eine Konstante ändern, kann es sehr gut andere Verwendungen derselben Konstante ändert in keinem Zusammenhang Code. Zum Beispiel können Sie eine Variable ‚(1 1) in irgendeiner Funktion, und in einer ganz anderen Funktion, starten Sie eine Liste mit‘ (1 1) vergleichen, und dann mehr Material, um es hinzuzufügen. Auf diese Funktionen ausgeführt wird, können Sie feststellen, dass die erste Funktion Dinge entspricht nicht mehr richtig, weil es jetzt versucht, die Variable zu vergleichen ‚(1 1 2 3 5 8 13), das ist, was die zweite Funktion zurückgegeben. Diese beiden Funktionen sind völlig unabhängig, aber sie haben eine Wirkung auf einander wegen der Verwendung von Konstanten. Auch verrückte schlechte Auswirkungen können passieren, wie eine ganz normale Liste Iteration plötzlich Endlosschleife.

Mit Zitat, wenn Sie brauchen eine konstante Liste, wie zum Vergleich. Verwenden Sie die Liste, wenn Sie das Ergebnis zu verändern.

Eine Antwort auf diese Frage sagt, dass QUOTE „Liste Datenstrukturen erzeugt“. Das ist nicht ganz richtig. ZITAT ist fundamentaler als diese. In der Tat ist QUOTE trivialer Betreiber: Sein Zweck zu ist verhindern etwas von überhaupt geschieht. Insbesondere ist es nicht alles schaffen.

Was (QUOTE X) sagt, ist im Grunde „nichts tun, gib mir nur X.“ X nicht eine Liste, wie in (QUOTE (A B C)) oder ein Symbol wie in (QUOTE FOO) sein muss. Es kann jeder was auch immer widersprechen. Tatsächlich ist das Ergebnis die Liste der Evaluierung, die von (LIST ‚QUOTE SOME-OBJECT) immer nur zurückkehren, um einig-OBJECT erzeugt wird, was auch immer es ist.

Nun, der Grund, dass (Zitat (A B C)) scheint, als ob es eine Liste, deren Elemente erstellt sind A, B und C ist, dass eine solche Liste wirklich ist, was es gibt; aber zum Zeitpunkt der QUOTE Form ausgewertet wird, ist die Liste der Regel bereits in Existenz für eine Weile (als Bestandteil des Angebotsformulars!), entweder durch den Lader oder den Leser vor der Ausführung des Codes.

Eine Implikation dieser, die Neulinge zu stolpern ziemlich oft dazu neigt, ist, dass es sehr unklug ist eine Liste von einer QUOTE Form zurück ändern. Daten von QUOTE zurückgegeben werden, für alle Absichten und Zwecke, zu betrachten als Teil des Code ausgeführt werden und soll daher als schreibgeschützt behandelt werden!

Das Zitat verhindert die Ausführung oder Auswertung einer Form, es stattdessen in Daten drehen. In der Regel können Sie die Daten ausführen, indem dann eval'ing es.

Zitat schafft Liste Datenstrukturen, zum Beispiel, sind die folgenden äquivalent:

(quote a)
'a

Es kann auch Listen verwendet werden, zu erstellen (oder Bäume):

(quote (1 2 3))
'(1 2 3)

Sie sind wahrscheinlich am besten aus einem Einführungs Buch über Lisp bekommen, wie Practical Common Lisp (die on-line verfügbar zu lesen).

Wenn wir wollen, selbst ein Argument übergeben, anstatt den Wert des Arguments von gibt dann verwenden wir zitieren. Es ist vor allem auf das Verfahren während der Weitergabe unter Verwendung von Listen, Paare und Atome bezogenen die nicht in Programmiersprache C zur Verfügung (die meisten Menschen beginnen Programmierung der C-Programmierung verwenden, also wir verwirrt) Dies ist Code in Programmiersprache Scheme, die ist ein Dialekt von Lisp und ich denke, Sie diesen Code verstehen können.

(define atom?              ; defining a procedure atom?
  (lambda (x)              ; which as one argument x
(and (not (null? x)) (not(pair? x) )))) ; checks if the argument is atom or not
(atom? '(a b c)) ; since it is a list it is false #f

Die letzte Zeile (Atom? ‚Abc) ist vorbei abc, wie es zu dem Verfahren ist zu prüfen, ob abc ein Atom ist oder nicht, aber wenn Sie passieren (Atom? Abc) dann überprüft es für den Wert von abc und passses der Wert zu. Da haben wir keinen Wert vorgesehen

In Emacs Lisp:

Was zitiert werden kann?

Listen und Symbole.

eine Reihe Zitiert wertet die Anzahl selbst: '5 ist die gleiche wie 5.

Was passiert, wenn Sie Listen zitieren?

Zum Beispiel:

'(one two) ausgewertet

(list 'one 'two), die ausgewertet

(list (intern "one") (intern ("two"))).

(intern "one") erstellt ein Symbol namens „Eins“ und speichern sie in einer „zentralen“ Hash-Karte, so zu jeder Zeit sagen Sie 'one dann das Symbol namens "one" wird in dieser zentralen Hash-Karte nachgeschlagen werden.

Was aber ist ein Symbol?

Zum Beispiel in OO-Sprachen (Java / Javascript / Python) ein Symbol als ein Objekt dargestellt werden könnte, die eine name Feld hat, die die Namen wie "one" oben Symbols ist, und Daten und / oder Code können mit in Verbindung gebracht werden es diese Aufgabe.

So ein Symbol in Python implementiert werden als:

class Symbol:
   def __init__(self,name,code,value):
       self.name=name
       self.code=code
       self.value=value

In Emacs Lisp zum Beispiel ein Symbol kann 1) Daten zugeordnet haben und (zugleich - für das gleiche Symbol) 2) Code mit ihm verbunden - je nach Kontext, entweder die Daten oder den Code aufgerufen wird .

Zum Beispiel in Elisp:

(progn
  (fset 'add '+ )
  (set 'add 2)
  (add add add)
)

ausgewertet 4.

Da (add add add) auswertet wie:

(add add add)
(+ add add)
(+ 2 add)
(+ 2 2)
4

So zum Beispiel mit der Symbol Klasse, die wir oben in Python definiert, diese add elisp-Symbol könnte als Symbol("add",(lambda x,y: x+y),2) in Python geschrieben werden.

Vielen Dank für Leute im IRC #emacs für Symbole und Zitate mir zu erklären.

Quote gibt die interne Darstellung ihrer Argumente. Nach dem Pflug durch viel zu viele Erklärungen, was Zitat nicht zu tun, das ist, wenn die Glühbirne geht. Wenn die REPL nicht Funktionsnamen in Großbuchstaben umwandeln, wenn ich sie zitiert, könnte es nicht dämmerte mir haben.

So. Gewöhnliche Lisp Funktionen konvertieren ihre Argumente in eine interne Darstellung, bewerten die Argumente und die Funktion anzuwenden. Zitat konvertiert ihre Argumente in eine interne Darstellung, und nur zurückgibt, dass. Technisch gesehen ist es richtig, dass Zitat sagt zu sagen: „nicht auswerten“, aber als ich versuchte zu verstehen, was es tat, mir zu sagen, was es nicht frustrierend war nicht zu tun. Mein Toaster nicht ausgewertet Lisp Funktionen entweder; aber das ist nicht, wie Sie erklären, was ein Toaster der Fall ist.

Anoter kurze Antwort:

quote bedeutet dies, ohne zu bewerten und Backquote ist Zitat, aber verlassen Hintertüren .

Ein gutes referrence:

Emacs Lisp-Referenzhandbuch sehr deutlich machen,

9.3 Zitiert

Die spezielle Form Zitat liefert dessen einziges Argument, wie geschrieben, ohne es zu bewerten. Dies bietet eine Möglichkeit, konstante Symbole und Listen aufzunehmen, die nicht selbst Auswertung Objekte sind, in einem Programm. (Es ist nicht notwendig, sich selbst zu bewerten Objekte wie Zahlen, Strings zu zitieren, und Vektoren.)

Sonderform: Zitat Objekt

This special form returns object, without evaluating it. 

Weil Zitat in Programme so oft verwendet wird, liefert Lisp eine bequeme Lese Syntax für sie. Ein Apostroph ( ‚'‘) durch eine Lisp-Objekt gefolgt (in Lese Syntax) erweitert, um eine Liste, deren erstes Element Zitat, und dessen zweites Element das Objekt. Somit ist die Lese Syntax ‚x eine Abkürzung für (Zitat x).

Hier sind einige Beispiele von Ausdrücken, das Zitat verwenden:

(quote (+ 1 2))
     ⇒ (+ 1 2)

(quote foo)
     ⇒ foo

'foo
     ⇒ foo

''foo
     ⇒ (quote foo)

'(quote foo)
     ⇒ (quote foo)

9.4 Backquote

Backquote Konstrukte können Sie eine Liste zitieren, sondern selektiv Elemente dieser Liste auszuwerten. Im einfachsten Fall ist es identisch mit der speziellen Form Zitat (im vorhergehenden Abschnitt beschrieben, siehe Zitiert). Zum Beispiel ergeben diese beiden Formen identische Ergebnisse:

`(a list of (+ 2 3) elements)
     ⇒ (a list of (+ 2 3) elements)

'(a list of (+ 2 3) elements)
     ⇒ (a list of (+ 2 3) elements)

Die spezielle Markierung ‚‘ innerhalb des Arguments Backquote zeigt einen Wert, der nicht konstant ist. Der Emacs Lisp Auswerter wertet das Argument ‚‘ und legt den Wert in der Listenstruktur:

`(a list of ,(+ 2 3) elements)
     ⇒ (a list of 5 elements)

Die Substitution mit ‚‘ wird auch auf tieferen Ebenen der Listenstruktur erlaubt. Zum Beispiel:

`(1 2 (3 ,(+ 4 5)))
     ⇒ (1 2 (3 9))

Sie können auch einen Auswertungswert in der Ergebnisliste Spleiß, den speziellen Marker ‚@‘. Die Elemente der gespleißten Liste werden Elemente auf der gleichen Ebene wie die anderen Elemente der resultierenden Liste. Der entsprechende Code ohne Verwendung von ‚`‘ist oft nicht lesbar. Hier sind einige Beispiele:

(setq some-list '(2 3))
     ⇒ (2 3)

(cons 1 (append some-list '(4) some-list))
     ⇒ (1 2 3 4 2 3)

`(1 ,@some-list 4 ,@some-list)
     ⇒ (1 2 3 4 2 3)
Code is data and data is code.  There is no clear distinction between them.

Dies ist eine klassische Aussage jeden Lisp Programmierer weiß.

Wenn Sie einen Code notieren, wird dieser Code-Daten sein.

1 ]=> '(+ 2 3 4)
;Value: (+ 2 3 4)

1 ]=> (+ 2 3 4)
;Value: 9

Wenn Sie einen Code notieren, wird das Ergebnis Daten sein, die diesen Code darstellen. Also, wenn Sie mit Daten arbeiten wollen, das ein Programm darstellt Sie das Programm zitieren. Dies gilt auch für die Atom Ausdrücke, nicht nur für Listen:

1 ]=> 'code
;Value: code

1 ]=> '10
;Value: 10

1 ]=> '"ok"
;Value: "ok"

1 ]=> code
;Unbound variable: code

Angenommen, Sie eine Programmiersprache in Lisp eingebettet erstellen möchten - Sie werden mit Programmen arbeiten, die in Schema (wie '(+ 2 3)) notiert sind, und dass als Code in der Sprache, die Sie interpretiert erstellen, indem sie Programme eine semantische Interpretation zu geben. In diesem Fall müssen Sie Zitat verwenden, um die Daten zu halten, sonst wird es in externer Sprache ausgewertet werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top