Sprachen wie C, Java und C ++ erfordern alle Klammern um den gesamten Ausdruck , wenn sie in einem verwendet if
, while
oder switch
.
if (true) {
// Do something
}
im Gegensatz zu
if true {
// Do something
}
Das kommt mir merkwürdig vor, weil die Klammern überflüssig sind. In diesem Beispiel true
ist es ein einzelner Ausdruck für sich. Die Klammer ändert ihre Bedeutung in keiner mir bekannten Weise. Warum gibt es diese ungewöhnliche Syntax und warum ist sie so verbreitet? Gibt es einen Vorteil, den ich nicht kenne?
THEN
).if
Anweisung, sondern erstellen nur eine zusammengesetzte Anweisung.Antworten:
Es muss sein , einige Möglichkeit zu sagen , wo der Zustand endet und der Zweig beginnt. Dafür gibt es viele verschiedene Möglichkeiten.
In einigen Sprachen gibt es kein conditionals überhaupt , zB in Smalltalk, Selbst, Neusprech, Io, Ioke, Seph und Fancy. Die bedingte Verzweigung wird einfach wie jede andere Methode als normale Methode implementiert. Die Methode wird auf Booleschen Objekten implementiert und auf einem Booleschen Objekt aufgerufen. Auf diese Weise ist die Bedingung einfach der Empfänger der Methode, und die beiden Zweige sind zwei Argumente, z. B. in Smalltalk:
Falls Sie mit Java besser vertraut sind, entspricht dies dem Folgenden:
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 es ist nichts Besonderes erforderlich, um sie abzugrenzen:
Einige Sprachen verwenden Schlüsselwörter als Begrenzer, z. B. Algol, Ada, BASIC, Pascal, Modula-2, Oberon, Oberon-2, Active Oberon, Komponente Pascal, Zonnon, Modula-3:
In Ruby können Sie entweder ein Schlüsselwort oder ein Ausdruckstrennzeichen (Semikolon oder Zeilenvorschub) verwenden:
Go setzt voraus, dass die Zweige Blöcke sind, und lässt keine Ausdrücke oder Anweisungen zu, weshalb geschweifte 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:
Einige Sprachen verwenden andere nicht alphanumerische Zeichen, um die Bedingung abzugrenzen, z. B. Python:
Die Quintessenz lautet: Sie müssen in irgendeiner Weise feststellen, wo die Bedingung endet und der Zweig beginnt. Es gibt viele Möglichkeiten, Klammern sind nur eine davon.
quelle
Die Klammern sind nur dann nicht erforderlich, wenn Sie geschweifte Klammern verwenden.
Zum Beispiel wird ohne sie mehrdeutig.
quelle
if
: Basic, Assembly, Python, Bash / Zsh, Tcl, Batch, Brainfuck oder Maschinencode. Fehlende Klammern machen nur dannif
mehrdeutig, wenn die Sprache so gestaltet wurde, dass sie von ihnen abhängt.if Condition then ...
.{}
obligatorisch und erfordert daher keine Parens um den Ausdruck. Nicht nur, dass keine Parens erforderlich sind, sondern wenn ich mich erinnere, dass das Hinzufügen von Parens einen Kompilierungsfehler verursachen würde - sie sind verbotenKlammern in einer
if
Anweisung haben nicht die gleiche Bedeutung wie Klammern, die in einem arithmetischen Ausdruck verwendet werden. Klammern in einem arithmetischen Ausdruck werden zum Gruppieren von Ausdrücken verwendet. Klammern in einerif
Anweisung werden verwendet, um den Booleschen Ausdruck abzugrenzen. das heißt, den booleschen Ausdruck vom Rest derif
Anweisung zu unterscheiden.In einer
if
Anweisung führen Klammern keine Gruppierungsfunktion aus (obwohl Sie in derif
Anweisung weiterhin Klammern verwenden können, um arithmetische Ausdrücke zu gruppieren. Der äußere Satz von Klammern dient dann zur Begrenzung des gesamten booleschen Ausdrucks). Das Erfordernis vereinfacht den Compiler, da sich der Compiler darauf verlassen kann, dass diese Klammern immer vorhanden sind.quelle
IF primary_expression statement
. Beachten Sie, dass letzteres ebenso eindeutig ist.primary_expression
nicht von einem Präfix-Operator in einer Ausdrucksanweisung unterschieden werden kann. So kopieren Sie Telastyn Antwort,if true ++ x;
. Wenn leere Anweisungen vorhanden sind,if a & f;
kann dies entweder eine leere Anweisung und eine binäre Anweisung&
innerhalb der Bedingung oder eine unäre&
Anweisung am Anfang der Anweisung sein. Wenn Sie jedoch Klammern verwenden, gibt es genau eine Übereinstimmung für die Eröffnung (IDENTIFIER
,CONSTANT
,STRING_LITERAL
und'(' expression ')'
.Wie andere bereits teilweise ausgeführt haben, liegt dies daran, dass Ausdrücke auch gültige Anweisungen sind und bei einem Block mit nur einer Anweisung geschweifte Klammern weggelassen werden können. Dies bedeutet, dass Folgendes nicht eindeutig ist:
Weil es so interpretiert werden könnte:
Anstatt von:
In einer Reihe von Sprachen (z. B. Python) können Sie die Klammern umgehen, haben aber immer noch einen Endbedingungsmarker:
Sie haben jedoch Recht, dass wir eine Sprache definieren könnten , in der die Klammern niemals erforderlich sind: Eine Sprache, in der ein Ausdruck keine gültige Aussage ist, wird dieses Problem nicht haben.
Leider bedeutet dies, dass Dinge wie:
Es 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 voranzustellen, wie z
[statement]
.Jetzt verschwindet die Zweideutigkeit, da Sie schreiben müssten:
Aber wie Sie sehen, ist eine solche Sprache nicht weit verbreitet, da es viel besser ist, die Klammer um eine
if
Bedingung (oder ein:
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 ein solcher Marker nicht erforderlich wäre. Das Problem ist: Die Sprache wäre extrem seltsam, da Sie für die gleichen Aufgaben in einem Ausdruck oder einer Anweisung eine völlig andere Syntax verwenden müssten.Eine Sache, die mir in den Sinn kommt, zwei getrennte Syntaxen ohne solch einen expliziten Marker zu haben, wäre zum Beispiel: Erzwinge Anweisungen, Unicode-Symbole zu verwenden (also anstatt
for
eine Unicode-Variation der Buchstaben zu verwendenf
,o
undr
), während Ausdrücke zu sein Nur ASCII.quelle
discard
seinen Wert in Nim explizit angeben . Dies geschieht jedoch nur aus Gründen der Typensicherheit und nicht aus syntaktischen Gründen.?
simbol ist in diesem Beispiel eine Funktion nach PP). Es gibt keine;
. Sicher, es braucht einen Marker für die Fortsetzung, aber davon wird abgeraten. harbour.github.io/doc/clc53.html#if-cmd . Der Compiler ist schnell und einfach (erstellt mit Bison / Flex).if
,while
ecc begrenzt sind im Vergleich zu generischen Ausdrücke in anderen Sprachen verwendet. Klar: Wenn Sie mehr als zwei syntaktische Kategorien haben (wie Aussage, Ausdruck, logischer Ausdruck, Kaffeezubereitungsausdruck, ...), können Sie mit etwas Freiheit handeln.Es ist üblich, dass Sprachen der C-Familie diese Klammern benötigen, jedoch nicht universell.
Einer von Perl 6 ist stärker spürbar syntaktischen Änderungen ist , dass sie die Grammatik modifiziert , so dass Sie nicht die Klammern geben müssen
if
,for
und ähnliche Bedingungen Aussagen. So etwas ist in Perl 6 absolut gültig:wie es ist
Da es sich jedoch nur um Ausdrücke handelt, können Sie sie nach Belieben 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:
Mir scheint, dass ein Merkmal moderner C-inspirierter Sprachen darin besteht, sich solche Dinge anzuschauen und sich zu fragen, ob sie entfernt werden sollen.
quelle
if
Konstrukte oder Schleifenkonstrukte mit BLOCKs werden die Parens benötigt, z . B. inif ( $x == 4 ) { ... }
oderforeach my $foo ( @bar ) { ... }
. Wenn die Postfix-Notation verwendet wird, sind die Parens wie inreturn unless $foo;
oder optional++$x while s/foo/bar/g;
.Es gibt einen Aspekt, der mich überrascht, dass keine der vorhandenen Antworten zur Sprache gebracht hat.
C und viele C-Derivate und Look-Alikes haben die Besonderheit, dass der Wert einer Zuweisung der zugewiesene Wert ist. Dies hat zur Folge, dass eine Zuweisung dort verwendet werden kann, wo ein Wert erwartet wird.
Dies ermöglicht es Ihnen, Dinge wie zu schreiben
oder
oder
(was implizit so behandelt wird,
while (n < m && *p1++ = *p2++ != 0) { n++; }
weil C eine Abweichung von Null als wahr behandelt; ich denke übrigens, das ist nur ungefähr strncpy () in der C-Standardbibliothek)oder auch
und es ist alles gültig. Nicht alle syntaktisch gültigen Kombinationen sind notwendigerweise nützlich (und moderne Compiler warnen speziell vor Zuweisungen innerhalb von Bedingungen, da es sich um einen häufigen Fehler handelt), aber ein Teil davon ist tatsächlich nützlich.
Das Parsen solcher Anweisungen wäre wahrscheinlich weitaus schwieriger, wenn nicht eindeutig festgestellt werden könnte, wo der bedingte Ausdruck beginnt und endet.
Klammern wurden bereits verwendet, um Funktionsnamen von Funktionsargumenten abzugrenzen. Ich denke, sie waren eine logische Wahl, um auch Schlüsselwörter von Schlüsselwortargumenten abzugrenzen.
Natürlich könnten alternative Syntaxen definiert werden, um dasselbe zu tun. Dies würde jedoch die Komplexität erhöhen, insbesondere im Parser, der sich dann mit zwei verschiedenen Syntaxsätzen für weitgehend dasselbe befassen müsste. Bereits bei der Entwicklung von C war die Rechenleistung (sowohl in Bezug auf die Fähigkeit zur Eingabe von Zahlen als auch auf den Arbeitsspeicher und die Speicherkapazität) äußerst begrenzt. Alles, was die Komplexität zu geringen oder keinen Kosten für die Lesbarkeit verringerte, war mit ziemlicher Sicherheit eine willkommene Änderung.
Die Verwendung von Klammern mag heute ein wenig archaisch erscheinen, aber wenn jemand mit der Sprache vertraut ist, beeinträchtigt dies nicht die Lesbarkeit im Vergleich zu einer anderen Syntax, die in der Lage ist, dieselben Dinge auszudrücken.
quelle
Der Grund ist meistens Geschichte.
Zum Zeitpunkt, als der erste C-Compiler geschrieben wurde, gab es auf Computern nur sehr wenige RAM-, CPU- und Compiler-Programme, die mit wenigen Tools „von Hand“ geschrieben wurden, um den Compiler-Autoren zu helfen. Daher war die Implementierung komplexer Regeln in einem Compiler kostspielig . C ++, C #, Java usw. sollten für C-Programmierer einfach zu erlernen sein, daher wurden keine „unnötigen“ Änderungen vorgenommen.
In "c like" -Sprachen
if, while, etc
erfordern conditionals ( ) keinen explizitenblock
Off-Code. Sie können einfach eine einfache Anweisung verwenden.oder Sie können Anweisungen zu einer kombinieren,
compound statement
indem Sie sie mit in einfügen{}
Wir möchten, dass der Compiler Fehler findet, die wir machen, und eine Fehlermeldung ausgibt, die wir verstehen können.
quelle
Java und C ++ wurden beide entwickelt, nachdem C eine sehr beliebte Programmiersprache geworden war. Eine Überlegung bei der Gestaltung jeder dieser Sprachen war, dass sie C-Programmierer ansprechen und diese Programmierer auffordern würde, die neue Sprache zu verwenden. (Ich war einer der C-Programmierer, die sie erfolgreich umwarben.) C ++ wurde außerdem so entworfen, dass es (fast) mit C-Code austauschbar ist. Um angenommen ist viel von C diese Ziele, sowohl C ++ und Java zu unterstützen Syntax, einschließlich der Klammern um die Bedingungen
if
,while
undswitch
Aussagen.Daher ist der Grund, warum alle diese Sprachen Klammern um die Bedingungen dieser Anweisungen benötigen, der, dass C dies tut, und die Frage ist wirklich nur, warum C diese Klammern benötigt.
Die Ursprünge der C-Sprache werden in diesem Artikel von Dennis Ritchie beschrieben, einem der Hauptautoren seiner Entwicklung (einige könnten sogar den Hauptautor seiner Entwicklung nennen). Wie in diesem Artikel erwähnt, wurde C ursprünglich in den frühen 1970er Jahren als Systemprogrammiersprache für Computer mit extrem begrenztem Platz im Hauptspeicher entwickelt. Es war wünschenswert, eine Sprache zu haben, die über der Assemblersprache lag. Angesichts der zur Verfügung stehenden Ressourcen war jedoch auch die einfache Syntaxanalyse 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. Tatsächlichif(a==b)
waren vier ganze Zeichen kürzer als , da die Klammern auch Leerzeichen als Begrenzer von Symbolen ersetzen konntenIF a==b THEN
.In jedem Fall musste ein Gleichgewicht hergestellt werden zwischen der Fähigkeit des Menschen, in C geschriebene Programme zu lesen, zu schreiben und zu verstehen, der Fähigkeit eines Compilers, in C geschriebene Programme zu analysieren und zu kompilieren, und der Anzahl der Kilobyte (!). wäre sowohl für die Programmquelle als auch für den Compiler selbst erforderlich. Und in Klammern um die Bedingungen von
if
,while
undswitch
Aussagen stand, wie sich die Leute entschieden haben, dieses Gleichgewicht bei der Gestaltung von C. zu finden.Wie aus mehreren anderen Antworten hervorgeht, wurden, nachdem Sie die besonderen Umstände, unter denen C entwickelt wurde, entfernt haben, alle Arten von alternativen Syntaxformen für die Bedingungen verschiedener Programmiersprachen verwendet. Die Klammern kommen also wirklich nur zu einer Entwurfsentscheidung, die von einigen wenigen Personen unter bestimmten Einschränkungen zu einem bestimmten Zeitpunkt in der Geschichte getroffen wurde.
quelle
Viele begründen hier, dass ohne die Klammern die Syntax mehrdeutig wäre und implizieren stillschweigend, dass dies irgendwie schlimm oder gar eine unmögliche Situation wäre.
Tatsächlich haben Sprachen viele Möglichkeiten, mit Mehrdeutigkeiten umzugehen. Die Operatorrangfolge 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, bei der die Klammern um die Bedingung nicht erforderlich sind (so dass sie optional sind) und bei der in allen Fällen immer noch gültiger Code erstellt wird. Das Beispiel von
if a ++ b;
könnte als äquivalent zuif (a) ++b;
oder interpretiert werdenif (a++) b;
, was angemessener erscheint.Die Frage, warum Dennis Ritchie das () zur Pflicht gemacht hat (und dieses Meme daher für viele abgeleitete Sprachen prägt), ist eher sprachlich. Ich denke, der Gedanke, klar zu sagen, dass der Zustand 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.
quelle
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 einemthen
Schlüsselwort nicht erforderlich .then
dient zur Abgrenzungcondition
des Folgendenstatement
.Die schließende Klammer in C usw. funktioniert als
then
, und die öffnende ist formal überflüssig.Die obigen Ausführungen gelten für traditionell geparste Sprachen.
quelle