Warum erlaubt Clojure (Eval 3) obwohl 3 nicht zitiert wird?

8

Ich lerne Clojure und versuche, Leser, Zitate, Eval und Homonyme zu verstehen, indem ich Parallelen zu Pythons ähnlichen Merkmalen zeichne.

In Python besteht eine Möglichkeit, die Auswertung zu vermeiden (oder zu verschieben) darin, den Ausdruck in Anführungszeichen zu schreiben, z. %Code%. Sie können dies später mit '3 + 4' , z. eval ergibt eval('3 + 4') . (Wenn Sie nur Python-Werte angeben müssen, können Sie 7 function verwenden, anstatt die Anführungszeichen manuell hinzuzufügen.)

In Lisp verwenden Sie repr oder quote für die Quotierung und ' für die Auswertung, z. eval ergibt (eval '(+ 3 4)) .

Also wird in Python der "quoted" Stoff durch einen String repräsentiert, während er in Lisp durch eine Liste repräsentiert wird, die 7 als erstes Element hat.

Meine Frage, schließlich: Warum lässt Clojure quote zu, obwohl (eval 3) nicht zitiert wird? Ist es nur die Frage des Lisp-Stils (versuche, wo immer möglich eine Antwort anstelle eines Fehlers zu geben) oder gibt es andere Gründe dafür? Ist dieses Verhalten für Lisp essentiell oder nicht?

    
Aivar 27.12.2012, 00:40
quelle

4 Antworten

4

Andere Antworten haben die Mechanik erklärt, aber ich denke, der philosophische Punkt ist auf die verschiedenen Arten, wie Lisp und Python "Code" betrachten. In Python ist die einzige Möglichkeit, Code als String darzustellen, der Versuch, einen Nicht-String auszuwerten. Lisp hat umfangreichere Datenstrukturen für Code: Listen, Zahlen, Symbole und so weiter. Der Ausdruck (+ 1 2) ist also eine Liste, die ein Symbol und zwei Zahlen enthält. Wenn Sie eine Liste auswerten, müssen Sie zuerst jedes ihrer Elemente bewerten.

Es ist also ganz natürlich, im normalen Verlauf des Lisp-Codes eine Zahl auswerten zu müssen. Zu diesem Zweck werden Zahlen definiert, um "sich selbst auszuwerten", was bedeutet, dass sie nach der Bewertung gleich sind wie zuvor: nur eine Zahl. Die Funktion eval wendet die gleichen Regeln auf das leere "Code-Snippet" 3 an, das der Compiler beim Kompilieren des dritten Elements eines größeren Ausdrucks wie (+ 5 3) anwenden würde. Für Zahlen bedeutet das, es in Ruhe zu lassen.

    
amalloy 27.12.2012, 01:58
quelle
6

Die kurze Antwort wäre, dass Zahlen (und Symbole und Strings zum Beispiel) sich selbst auswerten. Quoting instruct lisp (der Leser) unbewertet was auch immer dem Zitat folgt. eval erhält dann diese Liste, wie Sie es geschrieben haben, aber ohne das Zitat, und bewertet sie dann (im Fall von (eval '(+ 3 4)) wird eval einen Funktionsaufruf ( + ) über zwei Argumente auswerten).

Was mit diesem letzten Ausdruck passiert, ist folgender:

  1. Wenn Sie die Eingabetaste drücken, wird der Ausdruck ausgewertet. Es enthält einen normalen Funktionsaufruf ( eval ) und einige Argumente.
  2. Die Argumente werden ausgewertet. Das erste Argument enthält ein Zitat, das dem Leser sagt, produzieren was hinter dem Zitat steht (die tatsächliche (+ 3 4) -Liste).
  3. Es gibt keine weiteren Argumente und der tatsächliche Funktionsaufruf wird ausgewertet. Dies bedeutet, dass die eval -Funktion mit der -Liste (+ 3 4) als Argument aufgerufen wird.
  4. Die Funktion eval führt die gleichen Schritte erneut aus, indem sie die normale Funktion + und die Argumente findet und sie anwendet, um das Ergebnis zu erhalten.
Diego Sevilla 27.12.2012 00:53
quelle
3

Was sollte 3 bewerten? Es macht am meisten Sinn, dass Lisp eine Zahl für sich selbst auswertet. Müssten wir verlangen, dass Zahlen im Code zitiert werden? Das wäre nicht sehr praktisch und extrem problematisch:

Anstelle von

%Vor%

wir müssten schreiben

%Vor%

Jede Nummer im Code müsste zitiert werden. Ein fehlendes Angebot würde einen Fehler auslösen. Das ist nichts, was man benutzen möchte.

Stellen Sie sich als Randnotiz vor, was passiert, wenn Sie eval in Ihrem Code verwenden möchten.

%Vor%

Oben wäre falsch. Zahlen müssten zitiert werden.

%Vor%

Oben wäre in Ordnung, aber zur Laufzeit einen Fehler zu generieren. Lisp wertet '3 auf die Zahl 3 aus. Der Aufruf von eval für die Zahl wäre jedoch ein Fehler, da sie in Anführungszeichen gesetzt werden müssen.

Also müssten wir schreiben:

%Vor%

Das ist nicht sehr nützlich ...

Zahlen haben sich in der Lisp-Historie immer selbst bewertet. Aber in früheren Lisp-Implementierungen waren einige andere Datenobjekte, wie Arrays, nicht selbstbewertend. Da dies eine große Fehlerquelle ist, haben Lisp-Dialekte wie Common Lisp definiert, dass alle Datentypen (außer Listen und Symbolen) sich selbst auswerten.

    
Rainer Joswig 27.12.2012 01:30
quelle
2

Um diese Frage zu beantworten, müssen wir uns die Definition von eval in lisp ansehen. Z.B. In CLHS gibt es eine Definition:

  

Syntax: eval form = & gt; Ergebnis *

     

Argumente und Werte:   Form - eine Form.
  Ergebnisse - die Werte, die sich aus der Bewertung der Form ergeben.

Wo form ist

  
  1. jedes Objekt, das ausgewertet werden soll.
  2.   
  3. ein Symbol, eine zusammengesetzte Form oder ein sich selbst auswertendes Objekt.
  4.   
  5. (für einen Operator, wie in <<operator>> form'') a compound form having that operator as its first element. Ein Angebotsformular ist ein   konstante Form. ""
  6.   

In Ihrem Fall ist die Zahl "3" self-evaluating object . Self-evaluating object ist a form that is neither a symbol nor a cons is defined to be a self-evaluating object . Ich glaube, dass wir für clojure einfach cons durch list in dieser Definition ersetzen können.

In clojure wird nur lists von eval als Funktionsaufruf interpretiert. Andere Datenstrukturen und Objekte werden als selbstevaluierende Objekte ausgewertet.

'(+ 3 4) ist gleich (list '+ 3 4) . ' (transformiert vom Leser in quote function) vermeide nur die Auswertung der gegebenen Form. Also nimmt im Ausdruck (eval '(+ 3 4)) eval die Listen-Datenstruktur ('+ 3 4) als Argument.

    
mobyte 27.12.2012 00:59
quelle

Tags und Links