it-swarm.com.de

Warum benötigen Sprachen Klammern um Ausdrücke, wenn sie mit "if" und "while" verwendet werden?

Sprachen wie C, Java und C++ erfordern alle Klammern um einen gesamten Ausdruck, wenn sie in einem if, while oder switch verwendet werden.

if (true) {
    // Do something
}

im Gegensatz zu

if true {
    // Do something
}

Das erscheint mir seltsam, weil die Klammern überflüssig sind. In diesem Beispiel ist true ein einzelner Ausdruck für sich. Die Klammern verändern ihre Bedeutung in keiner mir bekannten Weise. Warum gibt es diese seltsame Syntax und warum ist sie so verbreitet? Gibt es einen Vorteil, den ich nicht kenne?

68
Velovix

Es muss eine Methode geben, um festzustellen, wo die Bedingung endet und der Zweig beginnt. Dafür gibt es viele verschiedene Möglichkeiten.

In einigen Sprachen gibt es überhaupt keine Bedingungen , z. in Smalltalk, Self, Newspeak, Io, Ioke, Seph und Fancy. Die bedingte Verzweigung wird wie jede andere Methode einfach als normale Methode implementiert. Die Methode wird für boolesche Objekte implementiert und für einen booleschen Wert aufgerufen. Auf diese Weise ist die Bedingung einfach der Empfänger des Verfahrens, und die zwei Zweige sind zwei Argumente, z. in Smalltalk:

aBooleanExpression ifTrue: [23] ifFalse: [42].

Wenn Sie mit Java besser vertraut sind, entspricht dies dem Folgenden:

aBooleanExpression.ifThenElse(() -> 23, () -> 42);

In der LISP-Sprachfamilie ist die Situation ähnlich: Bedingungen sind nur normale Funktionen (eigentlich Makros) und das erste Argument ist die Bedingung, das zweite und dritte Argument sind die Zweige, also sind sie nur normale Funktionsargumente, und es gibt sie nichts Besonderes war nötig, um sie abzugrenzen:

(if aBooleanExpression 23 42)

Einige Sprachen verwenden Schlüsselwörter als Trennzeichen, z. ALGOL, Ada, BASIC, Pascal, Modula-2, Oberon, Oberon-2, aktives Oberon, Komponente Pascal, Zonnon, Modula-3:

IF aBooleanExpression THEN RETURN 23 ELSE RETURN 42;

In Ruby können Sie entweder ein Schlüsselwort oder ein Ausdruckstrennzeichen (Semikolon oder Zeilenumbruch) verwenden:

if a_boolean_expression then 23 else 42 end

if a_boolean_expression; 23 else 42 end

# non-idiomatic, the minimum amount of whitespace required syntactically
if a_boolean_expression
23 else 42 end

# idiomatic, although only the first newline is required syntactically
if a_boolean_expression
  23
else
  42
end

Go erfordert, dass die Zweige Blöcke sind und keine Ausdrücke oder Anweisungen zulassen, weshalb die geschweiften Klammern obligatorisch sind. Daher sind keine Klammern erforderlich, obwohl Sie sie hinzufügen können, wenn Sie möchten. Perl6 und Rust sind in dieser Hinsicht ähnlich:

if aBooleanExpression { return 23 } else { return 42 }

Einige Sprachen verwenden andere nicht alphanumerische Zeichen, um die Bedingung abzugrenzen, z. Python:

if aBooleanExpression: return 23
else: return 42

Die Quintessenz lautet: Sie benötigen eine Methode, um festzustellen, wo die Bedingung endet und der Zweig beginnt. Es gibt viele Möglichkeiten, Klammern sind nur eine davon.

156
Jörg W Mittag

Die Klammern sind nur unnötig, wenn Sie geschweifte Klammern verwenden.

if true ++ x;

Zum Beispiel wird ohne sie mehrdeutig.

70
Telastyn

Klammern in einer if -Anweisung haben nicht dieselbe Bedeutung wie Klammern, die in einem arithmetischen Ausdruck verwendet werden. Klammern in einem arithmetischen Ausdruck werden verwendet, um Ausdrücke zu gruppieren. Klammern in einer if -Anweisung werden verwendet, um den booleschen Ausdruck abzugrenzen. das heißt, um den booleschen Ausdruck vom Rest der if - Anweisung zu unterscheiden.

In einer if -Anweisung führen Klammern keine Gruppierungsfunktion aus (obwohl Sie in der if -Anweisung weiterhin Klammern verwenden können, um arithmetische Ausdrücke zu gruppieren. Der äußere Satz von Klammern dient dann zur Begrenzung der ganzer boolescher Ausdruck). Wenn Sie sie benötigen, wird der Compiler vereinfacht, da sich der Compiler darauf verlassen kann, dass diese Klammern immer vorhanden sind.

21
Robert Harvey

Wie andere bereits teilweise darauf hingewiesen haben, liegt dies daran, dass Ausdrücke auch gültige Anweisungen sind, und im Fall eines Blocks mit nur einer Anweisung können Sie geschweifte Klammern setzen. Dies bedeutet, dass Folgendes nicht eindeutig ist:

if true
    +x;

Weil es interpretiert werden könnte als:

if (true + x) {}

anstatt:

if (true) {+x;}

In einer Reihe von Sprachen (z. B. Python) können Sie die Klammern vermeiden, haben jedoch immer noch eine Endbedingungsmarkierung:

Wenn wahr:: + x 

Sie haben jedoch Recht, dass wir eine Sprache definieren könnten, in der die Klammern niemals benötigt werden: eine Sprache, in der ein Ausdruck ist Nicht Eine gültige Anweisung hat dieses Problem nicht.

Leider bedeutet dies, dass Dinge wie:

 ++x;
 functionCall(1,2,3);

wären keine gültigen Anweisungen, daher müssten Sie eine seltsame Syntax einführen, um solche Aktionen ausführen zu können, ohne Ausdrücke zu erstellen. Eine einfache Möglichkeit, dies zu tun, besteht darin, dem Ausdruck einfach einen Marker wie [statement] Vorzustellen:

[statement] ++x;
[statement] functionCall(1,2,3);

Jetzt verschwindet die Mehrdeutigkeit, da Sie schreiben müssten:

if true
    [statement] ++x;

Aber wie Sie sehen, ist eine solche Sprache meiner Meinung nach nicht weit verbreitet, da es viel besser ist, die Klammer um eine if- Bedingung (oder einen : Am Ende) zu setzen, als für jede Ausdrucksanweisung einen solchen Marker zu setzen.


Hinweis: Die Verwendung eines [statement] - Markers ist nur die einfachste Syntax, die ich mir vorstellen kann. Sie könnten jedoch zwei völlig unterschiedliche Syntaxen für Ausdrücke und Anweisungen ohne Mehrdeutigkeit zwischen ihnen haben, für die kein solcher Marker erforderlich wäre. Das Problem ist: Die Sprache wäre extrem seltsam, da Sie eine völlig andere Syntax verwenden müssten, um dieselben Dinge in einem Ausdruck oder einer Anweisung zu tun.

Eine Sache, die in den Sinn kommt, wenn zwei separate Syntaxen ohne einen solchen expliziten Marker vorhanden sind, ist beispielsweise: Anweisungen zur Verwendung von Unicode-Symbolen erzwingen (anstelle von for würden Sie also eine Unicode-Variation der Buchstaben f, o und r verwenden). während Ausdrücke ASCII) sein sollen.

16
Bakuriu

Es ist üblich, dass Sprachen der C-Familie diese Klammern benötigen, jedoch nicht universell.

Eine der auffälligeren syntaktischen Änderungen von Perl 6 besteht darin, dass sie die Grammatik so geändert haben, dass Sie die Klammern um die Bedingungen von if, for und ähnlichen Anweisungen nicht angeben müssen. So etwas ist in Perl 6 vollkommen gültig:

if $x == 4 {
    ...
}

wie es ist

while $queue.pop {
    ...
}

Da es sich jedoch nur um Ausdrücke handelt, können Sie sie bei Bedarf in Klammern setzen. In diesem Fall handelt es sich nur um gewöhnliche Gruppierungen anstelle eines erforderlichen Teils der Syntax wie in C, C #, Java usw.

Rust hat eine ähnliche Syntax wie Perl 6 in dieser Abteilung:

if x == 4 {
    ...
}

Es scheint mir, dass ein Merkmal moderner C-inspirierter Sprachen darin besteht, solche Dinge zu betrachten und sich über das Entfernen zu wundern.

10
Matthew Walton

Es gibt einen Aspekt, den ich überrascht bin, dass keine der vorhandenen Antworten zur Sprache gebracht wurde.

C und viele C-Derivate und Doppelgänger haben eine Besonderheit darin, dass der Wert einer Zuweisung ist der zugewiesene Wert. Eine Folge davon ist, dass eine Zuweisung kann verwendet werden, wenn a Wert wird erwartet.

Dies ermöglicht es Ihnen, Dinge wie zu schreiben

if (x = getValue() == 42) { ... }

oder

if (x == y = 47) { ... }

oder

unsigned int n = 0 /* given m == SOME_VALUE */;
while (n < m && *p1++ = *p2++) { n++; }

(was implizit als while (n < m && *p1++ = *p2++ != 0) { n++; } behandelt wird, weil C Nicht-Null als wahr behandelt; ich denke übrigens, das ist nur strncpy () in der C-Standardbibliothek)

oder auch

if (x = 17);

und alles ist gültig. Nicht alle syntaktisch gültigen Kombinationen sind notwendigerweise nützlich (und moderne Compiler warnen speziell vor Zuweisungen innerhalb von Bedingungen, da dies ein häufiger Fehler ist). , aber einiges davon ist tatsächlich nützlich.

Das Parsen solcher Aussagen wäre wahrscheinlich weitaus schwieriger, wenn es keinen eindeutigen Weg gäbe, um festzustellen, wo der bedingte Ausdruck beginnt und endet.

Klammern wurden bereits verwendet, um Funktionsnamen von Funktionsargumenten abzugrenzen. Ich denke, sie schienen eine natürliche Wahl zu sein, um Schlüsselwörter auch von Schlüsselwortargumenten abzugrenzen.

Sicher, alternative Syntaxen könnten definiert werden, um dasselbe zu tun. Dies würde jedoch die Komplexität erhöhen, insbesondere im Parser, der dann zwei weitgehend unterschiedliche Syntaxsätze für weitgehend dasselbe behandeln müsste. Zu der Zeit, als C entwickelt wurde, war die Rechenleistung (sowohl in Bezug auf die Fähigkeit zur Zahlenverarbeitung als auch auf den Arbeitsspeicher und die Speicherkapazität) äußerst begrenzt. Alles, was die Komplexität bei geringen oder keinen Kosten für die Lesbarkeit reduzierte, war mit ziemlicher Sicherheit eine willkommene Änderung.

Die Verwendung von Klammern mag heutzutage etwas archaisch erscheinen, aber es ist nicht so, dass jemand, der mit der Sprache vertraut ist, die Lesbarkeit im Vergleich zu einer anderen Syntax beeinträchtigt, die in der Lage ist, dieselben Dinge auszudrücken.

6
a CVn

Der Grund ist meistens Geschichte.

Zu der Zeit, als der erste C-Compiler geschrieben wurde, haben Computer nur sehr wenige RAMs, CPUs und Compiler, die mit wenigen Tools „von Hand“ geschrieben wurden, um Compiler-Autoren zu unterstützen. Daher komplexe Regeln waren kostspielig in einem Compiler zu implementieren. C++, C #, Java usw. wurden so konzipiert, dass C-Programmierer sie leicht erlernen können daher wurden keine „unnötigen“ Änderungen vorgenommen.

In "c like" -Sprachen erfordern Bedingungen (if, while, etc) Keinen expliziten block off-Code. Sie können einfach eine einfache Anweisung verwenden.

if (a == d) doIt()

oder Sie können Anweisungen zu einem compound statement kombinieren, indem Sie sie in {} einfügen.

Wir möchten, dass der Compiler Fehler findet, die wir machen, und als Fehlermeldung gibt, die wir verstehen können.

5
Ian

Viele hier argumentieren, dass die Syntax ohne die Klammern mehrdeutig wäre und implizit impliziert, dass dies irgendwie schlecht oder sogar eine unmögliche Situation wäre.

In der Tat haben Sprachen viele Möglichkeiten, mit Mehrdeutigkeiten umzugehen. Die Priorität des Operators ist nur eine Instanz dieses Themas.

Nein, Mehrdeutigkeit ist nicht der Grund für die Klammern. Ich denke, man könnte einfach eine Version von C erstellen, für die die Klammern um die Bedingung nicht erforderlich sind (wodurch sie optional sind) und die in allen Fällen immer noch gültigen Code erstellt. Das Beispiel von if a ++ b; Könnte so interpretiert werden, dass es if (a) ++b; oder if (a++) b; entspricht, was auch immer angemessener erscheint.

Die Frage, warum Dennis Ritchie das () obligatorisch gemacht hat (und damit dieses Mem für viele abgeleitete Sprachen prägt), ist eher sprachlich. Ich denke, der Gedanke, klar zu sagen, dass die Bedingung eher ein Ausdruck als ein Befehl ist, war der Vater des Gedankens.

Tatsächlich wurde C so konzipiert, dass es mit einem One-Pass-Parser analysiert werden kann. Die Verwendung einer Syntax mit obligatorischen Klammern um die Bedingung unterstützt diesen Aspekt.

3
Alfe

Java und C++ wurden beide entwickelt, nachdem C eine sehr beliebte Programmiersprache geworden war. Eine Überlegung bei der Gestaltung jeder dieser Sprachen war, dass es C-Programmierer ansprechen und diese Programmierer für die Verwendung der neuen Sprache werben würde. (Ich war einer der C-Programmierer, um die sie erfolgreich geworben haben.) C++ wurde zusätzlich so konzipiert, dass es (fast) mit C-Code austauschbar ist. Um diese Ziele zu unterstützen, haben sowohl C++ als auch Java einen Großteil der C-Syntax übernommen, einschließlich der Klammern um die Bedingungen von if, while und switch Anweisungen.

Daher ist der Grund, warum all diese Sprachen Klammern um die Bedingungen dieser Aussagen erfordern, der, dass C dies tut, und die Frage ist wirklich nur, warum C diese Klammern benötigt.

Die Ursprünge der C-Sprache sind in dieser Artikel von Dennis Ritchie, einem der Hauptautoren ihrer Entwicklung (einige könnten sogar sagen die Hauptautor seiner Entwicklung). Wie in diesem Artikel erwähnt, wurde C ursprünglich in den frühen 1970er Jahren als Systemprogrammiersprache für Computer mit extrem begrenztem Speicherplatz im Hauptspeicher entwickelt. Es war erwünscht, eine Sprache zu haben, die höher als die Assemblersprache war, aber angesichts der verfügbaren Ressourcen für die Arbeit war auch die einfache Analyse der Sprache wichtig. Das Erfordernis der Klammern würde es relativ einfach machen, den bedingten Code zu identifizieren.

Man könnte auch schließen, dass die Fähigkeit, Programme mit weniger Zeichen zu schreiben, als Vorteil angesehen wurde und zwei Klammern weniger Platz beanspruchen als das Schlüsselwort THEN, das zu dieser Zeit in FORTRAN und anderen Hochsprachen verwendet wurde; Da die Klammern auch Leerzeichen als Trennzeichen für Symbole ersetzen konnten, war if(a==b) vier ganze Zeichen kürzer als IF a==b THEN.

In jedem Fall musste ein gewisses Gleichgewicht hergestellt werden zwischen der Leichtigkeit, mit der Menschen in C geschriebene Programme lesen, schreiben und verstehen können, der Leichtigkeit, mit der ein Compiler in C geschriebene Programme analysieren und kompilieren kann, und der Anzahl der Kilobyte (!). wäre sowohl für die Programmquelle als auch für den Compiler selbst erforderlich. Und Klammern um die Bedingungen der Aussagen if, while und switch waren, wie die Leute beschlossen haben, dieses Gleichgewicht im Design von C zu finden.

Wie aus mehreren anderen Antworten hervorgeht, wurden, sobald Sie die besonderen Umstände, unter denen C entwickelt wurde, weggenommen haben, alle Arten alternativer Syntaxformen für die Bedingungen verschiedener Programmiersprachen verwendet. Die Klammern beruhen also wirklich nur auf einer Entwurfsentscheidung, die von einigen wenigen Personen unter bestimmten Einschränkungen zu einem bestimmten Zeitpunkt in der Geschichte getroffen wurde.

3
David K

Klammern um if -Bedingungen sind in Fortran, Cobol, PL/1, ALGOL, Algo-68, Pascal, Modula, XPL, PL/M, MPL usw. oder einer anderen Sprache mit then Schlüsselwort. then dient dazu, das condition von dem folgenden statement abzugrenzen.

Die schließende Klammer in C usw. fungiert als then, und die öffnende Klammer ist formal redundant.

Die obigen Ausführungen gelten für traditionell analysierte Sprachen.

0
user207421