2015-09-02 18 views
7

Ich weiß, dass dies ein Duplikat sein könnte, aber ich habe keine ausreichenden Antworten auf meine Beispiele gefunden. Was ist der Unterschied zwischen Aussagen und Ausdrücken? Dies ist eine Unterscheidung, die ich noch nicht vollständig erkannt habe. Ich weiß, dass Ausdrücke normalerweise alles sind, was einen Wert zurückgibt, wie zum Beispiel ein Literal oder eine Funktion. Anweisungen werden normalerweise als Befehle an den Interpreter bezeichnet, wie "Drucke das und das" oder "tue ... während". Aber ich verstehe es nicht.Was ist der Unterschied zwischen einem Ausdruck und einer Aussage?

Wäre es nicht sinnvoll zu sagen, dass Ausdruck ein Ausdruck ist, da es sich um eine Funktion handelt, die einen Eingang druckt (Eingang zu Ausgang)? Auch Leute sagen normalerweise, dass x = 1 eine Aussage ist, aber könnte dies nicht als Ausdruck betrachtet werden, wo der Zuweisungsoperator eine Funktion ist, die auf zwei Eingaben wirkt und die Ausgabe ist, dass sich x auf 1 bezieht? Schließlich könnte eine Flow-Control-Struktur wie wenn nicht. . . sonst wird als eine Dreiargumentfunktion betrachtet, in der eines der anderen Argumente basierend auf dem Wahrheitswert der ersten Eingabe zurückgegeben wird, was es zu einem Ausdruck macht?

Ich bin wahrscheinlich verwirrt, weil ich einen Hintergrund in LISP habe, wo alles ein Ausdruck ist. Es scheint, dass ich nicht vor dem Gedanken zurückschrecken kann, dass die meisten Programmierkonstrukte Ausdrücke in ihrem Kern sind. Könnte also jemand erklären, was wirklich der Unterschied zwischen einer sogenannten Aussage und einem Ausdruck ist?

+0

Die Antwort ist eher philosophisch als praktisch. Anweisungen haben typischerweise Nebenwirkungen, während Ausdrücke in der Regel eher algebraisch sind. In rein funktionalen Sprachen gibt es keine Aussagen. Das heißt, dass sogar diejenigen Dinge, die Nebenwirkungen (zum Beispiel zu einer Datei) ausführen, in Werten ausgedrückt werden, die (idealerweise) alle Mutationen darstellen - einschließlich Fehler. Imperative Sprachen verwenden Anweisungen zum Ausführen von beliebigem Code, z. B. zum Zuweisen eines Werts zu einer Variablen oder zum Drucken auf der Konsole und zum potenziellen Kommunizieren von Fehlern durch Ausnahmeausbreitung. –

+0

Die Unterscheidung hängt davon ab, von welcher Sprache Sie sprechen. In C ist "x = 1" ein Ausdruck und "x = 1;" ist eine Aussage. In Ada ist 'x: = 1 'kein Ausdruck, sondern' x: = 1; 'ist eine Aussage. –

Antwort

3

Ein Ausdruck ergibt einen Wert, eine Aussage macht etwas.

zB; in C return a+5; ist eine Anweisung, sie gibt eine Funktion aus, die dem Aufrufer den vom Ausdruck a+5 abgeleiteten Wert liefert.

Ob Ausdruck ein Ausdruck oder eine Aussage ist, hängt von der Sprache ab.

BASIC hat einen Ausdruck, der nicht funktional ist, sondern vom sompiler als Sonderfall gehandhabt wird. ähnlich Pascal hat write und writeln die auch Sonderfälle sind, nicht Funktion calle, auf der anderen Seite hat C puts() und printf(), die beide Funktionen sind. und ermöglicht dem Programmierer, ähnliche Funktionen zu schreiben, die auf die gleiche Weise funktionieren.

+0

Ein Ausdruck kann "etwas tun". – user2864740

+0

@ user2864740 vielleicht ist dann eine Unterscheidung zwischen einem Ausdruck mit Nebenwirkungen und einem ohne gerechtfertigt. – JPC

+1

@JPC Ich denke nicht, dass man die Nebenwirkungen von Ausdrücken diskutieren muss, um die Frage zu beantworten (obwohl es gut passt); Der Unterschied zwischen einer Anweisung und einem Ausdruck ist eine * Grammatik-Produktionsregel *. – user2864740

7

Die Definition von Ausdruck und Aussage - und selbst wenn es so etwas wie einen oder anderen - ist spezifisch für eine bestimmte Sprache und die Grammatik, die es beschreibt.

Nun, gehen wir:

  • A Aussage ist einige 'auswertbares Code' dass nicht in einem Ausdruck Kontext erscheint; und

  • Ein Ausdruck ist Code, der in einem Kontext erscheint, wo der sich ergebende Wert kann durch Substitution des Ausdrucks verbraucht werden.

{A sehr locker 'Definition', aber es gibt keine eine Sprache. Während einige Sprachen streng darauf abzielen, wann Nebenwirkungen auftreten können und nicht auftreten können - und Code, der ohne Ergebnis oder Nebeneffekt ausgeführt wird, ist nutzlos -, glaube ich nicht, dass die Diskussion solcher Unterschiede für die Unterschiede von grundlegender Bedeutung ist.}

Betrachten wir zum Beispiel printf in C. Dies ist eine Funktion, die Seite eine Nebenwirkung and it returns a value; Normalerweise wird der Rückgabewert ignoriert. Somit kann printf als erscheinen sowohl eine Aussage

printf("Hello world!"); 

und einen Ausdruck

if (8 == printf("Hello %s!", name)) { // .. 

(A-Funktionsaufruf mit dem Rückgabetyp void kann nur in einer Erklärung Kontext in C erscheinen, aber dies auferlegt vom Typ System und nicht der Parser.)

Ebenso nehmen Sie diese zwei Zeilen in JavaScript und x = (y = 2);. x = .. ist eine Aussage, während y = 2 ein Ausdruck ist, der einen Wert ergab.

In diesen beiden Beispielen sehen wir, dass es die Grammatik Produktion, die, wenn sie als Anweisung behandelt werden oder einen Ausdruck bestimmt ist.

Im Gegensatz Rubin können die 'Top-Level' Zuordnung als Ausdruck behandeln:

[1].map {|x| x = 2} 

Lassen Sie uns nun einen Peak nehmen eine Python (2.x). In diesem Fall print ist eine Aussage, weshalb diese Arbeit und nicht funktionieren, beziehungsweise:

print "Look ma, no parenthesis!" 
x = lambda y: print "Whoops!"  # invalid, print not an expression 

Und was ist bei if Konstrukte - sind diese Aussagen oder Ausdrücke? Auch hier kommt es auf die insbesondere Sprache. In C und Java sind dies klare Aussagen: Es gibt keine Möglichkeit, einen Ersatz für einen Wert zu verwenden.

Auf der anderen Seite, Scala (und Ruby) erlaubt es, solche Kontrollstrukturen als Ausdrücke verwendet werden, obwohl sie auch als Aussagen erscheinen:

var emotionalResponse = if (color == "green") { 
          log.cheer() 
          new Cheering() 
         } else { 
          new Tears() 
         } 

Puh. Das ist viel - und es ist nicht annähernd umfassend. Aber zurück zu der "Definition", auf die man bei der Betrachtung der verschiedenen obigen Beispiele so zurückblicken kann:

Wenn das fragliche Konstrukt kann auftreten, wo ein Wert benötigt wird (z. B. auf der rechten Seite) Hand-Seite einer Zuweisung, als ein Funktionsargument, als Eingabe für einen anderen Ausdruck), dann kann als ein Ausdruck behandelt werden; und ist definitiv ein Ausdruck, wenn in einem solchen Kontext. Wenn das Konstrukt an einer Stelle erscheint, an der der Wert nicht durch durch Ersetzung erreicht werden kann, ist es (oder vielmehr, kann als eine Anweisung fungieren).


Eine andere Klasse von Produktionen Zustand Erklärungen, wie eine Funktionsdeklarationen in C oder Klassendefinitionen in Java, und sind wohl keine Aussagen; Da das Folgende bereits so fragmentiert ist, ist dies genau das, was man bekommt.

+0

'printf()' ist keine Aussage. Der * Funktionsaufruf * ist die Anweisung: 'printf()' ist nur die Funktion, die aufgerufen wird. – EJP

+0

@EJP "ist eine Funktion .. kann als" erscheinen - obwohl ich offen für klarere Vorschläge bin. – user2864740

+0

@EJP: In printf ("Hello") '' ist ein Ausdruck, keine Aussage. 'printf (" Hallo ");' ist eine Aussage. Eine * Ausdruckanweisung * ist eine bestimmte Art von Anweisung, die aus einem (optionalen) Ausdruck gefolgt von einem Semikolon besteht. (Die NULL-Anweisung wird aus irgendeinem Grund als Ausdrucksanweisung behandelt.) –

0

Die Antwort ist philosophischer als praktisch. Anweisungen haben typischerweise Nebenwirkungen, während Ausdrücke in der Regel eher algebraisch sind.

In rein funktionalen Sprachen gibt es keine Anweisungen. Das heißt, dass sogar diejenigen Dinge, die Nebenwirkungen (zum Beispiel zu einer Datei) ausführen, in Werten ausgedrückt werden, die (idealerweise) alle Mutationen darstellen - einschließlich Fehler.

Imperative Sprachen verwenden Anweisungen zum Ausführen von beliebigem Code, z. B. zum Zuweisen eines Werts zu einer Variablen oder zum Drucken auf der Konsole und zum potenziellen Kommunizieren von Fehlern durch Ausnahmeausbreitung.

Rein funktionale Ausdrücke reduzieren lediglich den kognitiven Overhead im Umgang mit Mutationen, indem sie diese Mutationen als Werte in und an sich aussetzen. Kombinieren Sie dies mit dem Mustervergleich, und Sie sind gezwungen, alle Erfolgs- und Fehlerszenarien explizit zu behandeln und sie folglich in Werte umzuwandeln, um Fehler explizit zuzuordnen oder zu filtern.

Imperative Anweisungen sind nicht erforderlich, um Fehler als Werte zu offenbaren, und daher besteht immer die Möglichkeit, dass willkürlicher Code in einer nichtsahnenden Methode so existiert, dass er leicht übersehen wird. Anweisungen, z. B. Methodenaufrufe oder Variablenzuweisungen (x = y = z()), können im Allgemeinen der Form eines Ausdrucks entsprechen und dennoch beliebigen Code ausführen und Fehler nicht als Werte kommunizieren.

Am Ende können Sie Mutation nicht vermeiden. Sie können es jedoch expliziter machen. Das heißt, Aussagen und Ausdrücke unterscheiden sich hauptsächlich in einer philosophischen Art und Weise, beide existieren, um die gleiche Frage zu beantworten - wie sollten wir Mutationen im Kontext der Codeausführung offenlegen?

Verwandte Themen