In vielen Sprachen (eine breite Liste von C bis JavaScript):
- durch Kommas
,
getrennte Argumente (zBfunc(a, b, c)
), während - Semikolons
;
trennen sequentielle Anweisungen (zBinstruction1; instruction2; instruction3
).
Warum ist diese Zuordnung für for-Schleifen in denselben Sprachen umgekehrt :
for ( init1, init2; condition; inc1, inc2 )
{
instruction1;
instruction2;
}
statt (was mir natürlicher erscheint)
for ( init1; init2, condition, inc1; inc2 )
{
instruction1;
instruction2;
}
?
Sicher, for
ist ( in der Regel) keine Funktion, sondern Argumente ( das heißt init
, condition
, increment
) verhalten sich eher wie Argumente einer Funktion als eine Folge von Anweisungen.
Liegt es an historischen Gründen / einer Konvention oder gibt es eine gute Begründung für den Austausch von ,
und ;
in Schleifen?
programming-languages
syntax
loops
Piotr Migdal
quelle
quelle
;
nicht|
?" (oder Warum verwenden wir "sonst" nicht "anders"? )), die nicht für eine Sprache, sondern für eine große Anzahl von ihnen gilt. Eine Antwort, die z. B. "in C als Kurzform für while-Schleife erstellt wurde (und mehrere Anweisungen für inc wurden erst später in Betracht gezogen), und die nicht geändert werden sollte, um Irritationen der Programmierer zu vermeiden", wäre vollkommen in Ordnung.Antworten:
Technisch ist das Mapping nicht "umgekehrt".
In Wirklichkeit haben wir hier einen anderen syntaktischen Kontext, in dem dieselben Symbole unterschiedlich verwendet werden. Wir vergleichen nicht Gleiches mit Gleichem, daher gibt es keine Abbildung und kein starkes Argument für eine konsistente Abbildung auf der Grundlage semantischer Konsistenz.
Warum also nicht umgekehrt?
Nun, ich denke, die Gründe dafür liegen in der "natürlichen" Bedeutung von
,
und;
. In englischer Sprache ist ein Semikolon "stärker" als ein Komma, und die Glyphe für ein Semikolon ist sichtbarer als ein Komma. Diese beiden Dinge lassen das derzeitige Arrangement (für mich!) Natürlicher erscheinen.Die einzige Möglichkeit, sicher zu wissen, warum die Syntax gewählt wurde, wäre, wenn die C-Designer uns sagen könnten, was sie im Jahr 1970 gedacht haben. Ich bezweifle, dass sie eine klare Erinnerung an technische Entscheidungen haben, die so weit zurückliegen.
Ich kenne keine Sprache vor C, die eine C-ähnliche Syntax für "for" -Schleifen verwendet hat:
Donal Fellows bemerkt, dass BCPL und B kein äquivalentes Konstrukt hatten.
Die Äquivalente FORTRAN, COBOL und Algol-60 (und Pascal) waren weniger aussagekräftig und besaßen Syntaxen, die nicht der C-for-Syntax entsprachen.
Aber Sprachen wie C, C ++ und Java, die nach C kamen, leihen eindeutig ihre "for" -Syntax von C.
quelle
,
vs;
) ist also (schwächer vs stärkerer Bruch), nicht (Tupel vs Sequenzteiler), oder? Noch ist für mich nicht klar, ob Argumente oder Anweisungen stärkere Unterbrechungen benötigen (wie in vielen Fällen für eine Folge von Anweisungen, Unterbrechungen sind implizit (siehe z. B. JavaScript (z. B.i++[line break]j++
)), aber zumindest verstehe ich jetzt, warum die aktuelle Konvention ist nicht "offensichtlich umgekehrt".FOR i = e1 TO e2 BY e3 DO c
(e1..e3-Ausdrücke, c-Befehl), der der BASIC-Syntax ähnlicher ist. Quellefor
Syntax wurde in C eingeführt (es war nicht in B oder BCPL).Wir schreiben Schleifen wie:
Die Sprache könnte so definiert sein, dass Schleifen wie folgt aussehen:
Denken Sie jedoch an dieselbe Schleife, die mit einer while-Schleife implementiert wurde:
Beachten Sie, dass die
x=0
undx++
sind Aussagen, beendet durch Semikolons. Es sind keine Ausdrücke wie in einem Funktionsaufruf. Semikolons werden zum Trennen von Anweisungen verwendet, und da zwei der drei Elemente in einer for-Schleife Anweisungen sind, wird dies dort verwendet. Eine for-Schleife ist nur eine Abkürzung für eine solche while-Schleife.Darüber hinaus verhalten sich die Argumente nicht wirklich wie Argumente für eine Funktion. Die zweite und dritte werden wiederholt ausgewertet. Es ist wahr, dass sie keine Sequenz sind, aber sie sind auch keine Funktionsargumente.
Die Tatsache, dass Sie Kommas verwenden können, um mehrere Anweisungen in der for-Schleife zu haben, können Sie auch außerhalb der for-Schleife ausführen.
ist eine absolut gültige Aussage auch außerhalb einer for-Schleife. Ich kenne keine praktische Verwendung außerhalb der for-Schleife. Der Punkt ist jedoch, dass Kommas Anweisungen immer unterteilen. Dies ist keine Besonderheit der for-Schleife.
quelle
x = 0; y = 0;
und (in der geschweiften Klammer) beginnen könntenx++; y++;
...;
ist eine Abfolge von Aussagen selbstverständlich , die keine Aussagen trennt (ist es also nur so, dass der Geschmack unterschiedlich ist?). Und in der gegenwärtigen Konvention endet man sowieso gelegentlich damit, Folgen von Anweisungen durch Kommas zu trennen ...(foo)?bar++, qux++:bletch
der?:
Ausdruck zwei Dinge und nicht nur eine tun soll? Der Rückgabewertfoo
ist truequx
, aber beidebar
undqux
werden inkrementiert.In C und C ++ ist dies der Kommaoperator, nicht nur ein Komma.
Die Grammatik für eine
for
Schleife ist so etwas wieIm Falle Ihrer Frage:
Beachten Sie, dass Sie mit dem Komma-Operator mehrere Aktionen in einer Anweisung ausführen können (wie es der Compiler sieht). Wenn Ihr Vorschlag umgesetzt würde, wäre die Grammatik unklar, wann der Programmierer beabsichtigt, eine Komma-Operator-Anweisung oder ein Trennzeichen zu schreiben.
Kurz gesagt,
;
bedeutet das Ende einer Anweisung. Einefor
Schleife ist ein Schlüsselwort, gefolgt von einer Liste optionaler Anweisungen, die von umgeben sind()
. Die Komma-Operator-Anweisung ermöglicht die Verwendung,
in einer einzelnen Anweisung.quelle
for
erlaubt die Syntax einer Schleife explizit eine Anweisung (Deklaration) als ersten Teil. (C ++ erlaubte Deklarationen im Gegensatz zu seinem Vorgänger C89 mitten in der Funktion). Sie können solche Aussagen nicht über mehrere Sprachen hinweg verallgemeinern, auch nicht für zwei Sprachen, die so nah wie C und C ++ sind.for ( {<expression>}? ; {<expression>}? ; {<expression>}? ) <statement>
für C undfor ( for-init-statement; conditionopt ; expressionopt ) statement
für C ++ verwenden --- Das ';' bedeutet nicht nur einen Anweisungsabschluss. Auf eine for-Schleife folgen keine Anweisungen in ().Es gibt keine konzeptionelle Umkehrung.
Semikolons in C stehen für größere Unterteilungen als Kommas. Sie trennen Aussagen und Erklärungen.
Die Hauptunterteilung in der for-Schleife besteht darin, dass es drei Ausdrücke (oder eine Deklaration und zwei Ausdrücke) und einen Body gibt.
Die Kommas, die Sie in C for-Schleifen sehen, sind nicht Teil der Syntax der for-Schleife. Sie sind nur Manifestationen des Kommaoperators.
Kommas sind wichtige Trennzeichen zwischen Argumenten in Funktionsaufrufen und zwischen Parametern in Funktionsdeklarationen. Semikolons werden jedoch nicht verwendet. Die for-Schleife ist eine spezielle Syntax. es hat nichts mit Funktionen oder Funktionsaufrufen zu tun.
quelle
Vielleicht ist dies etwas spezielles für C / C ++, aber ich poste diese Antwort, da die Syntax der von Ihnen beschriebenen Sprachen hauptsächlich von der C-Syntax beeinflusst wird.
Abgesehen davon, dass die zuvor beantworteten Fragen aus technischer Sicht zutreffen, liegt dies auch daran, dass in C (und C ++) das Komma tatsächlich ein Operator ist, den Sie sogar überladen können . Die Verwendung eines Semikolon-Operators (
operator;()
) würde möglicherweise das Schreiben von Compilern erschweren, da das Semikolon der Terminator für den axiomatischen Ausdruck ist.Das Interessante daran ist, dass das Komma in der gesamten Sprache als Trennzeichen verwendet wird. Es scheint, als sei der Komma-Operator eine Ausnahme, der hauptsächlich verwendet wird, um
for
-loops mit mehreren Bedingungen zum Laufen zu bringen. Also, was ist der Deal?In der Tat das
operator,
ist das gleiche wie in den Definitionen, Argumentlisten zu tun gebaut, und so weiter: Es hat Build gewesen separates Ausdrücke - etwas , das syntaktische Konstrukt,
nicht tun kann. Sie kann nur das trennen, was in der Norm definiert wurde.Das Semikolon wird jedoch nicht getrennt - es wird beendet . Und dies führt uns auch zurück zu der ursprünglichen Frage:
Das Komma trennt die Ausdrücke in die drei Schleifenteile, während das Semikolon einen Teil (Initialisierung, Bedingung oder nachträglicher Gedanken) der Schleifendefinition beendet.
Neuere Programmiersprachen (wie C #) erlauben möglicherweise keine Überladung des Komma-Operators, aber sie haben höchstwahrscheinlich die Syntax beibehalten, da sich eine Änderung irgendwie unnatürlich anfühlt.
quelle
for
Anweisung wird das;
Symbol einfach als Trennzeichen verwendet. Es trennt die 3 syntaktischen Teile der Anweisung. Es gibt kein drittes Semikolon zum "Beenden" der progressiven Ausdrucksliste. Es wird mit einem anderen Token beendet -)
.Für mich sind sie eher weniger bedeutungsähnlich zu ihrem sprachlichen Sinn. Kommas werden bei Listen und Semikolons mit mehreren getrennten Teilen verwendet.
In haben
func(a, b, c)
wir eine Liste von Argumenten.instruction1; instruction2; instruction3
ist vielleicht eine Liste, aber eine Liste von separaten und unabhängigen Anweisungen.Während
for ( init1, init2; condition; inc1, inc2 )
wir in sind, haben wir drei separate Teile - eine Liste von Initialisierungen, eine Bedingung und eine Liste von inkrementellen Ausdrücken.quelle
Der einfachste Weg, es zu sehen, ist der folgende:
ist:
Mit anderen Worten, das Ding x = 0 ist eigentlich eher eine Anweisung als ein Parameter. Sie fügen dort eine Aussage ein. Daher werden sie durch Semikolon getrennt.
In der Tat gibt es keine Möglichkeit, sie durch Komma zu trennen. Wann fügen Sie das letzte Mal Dinge wie x <10 als Parameter ein? Sie tun dies, wenn Sie x <10 einmal rechnen und das Ergebnis dieser Operation als Parameter einfügen möchten. In der Kommawelt würden Sie also x <10 setzen, wenn Sie den Wert von x <0 an eine Funktion weitergeben möchten.
Hier legen Sie fest, dass das Programm bei jedem Durchlauf der Schleife x <10 prüfen soll. Das ist also eine Anweisung.
x ++ ist definitiv eine andere Anleitung.
Das sind alles Anweisungen. Sie sind also durch ein Semikolon getrennt.
quelle
for
switch
oderreturn
innerhalb der for-Schleifendefinition (dhfor(int i = 0; if(i > 1024) { return; } ; switch (i % 3) { case 0; case 1: i++; case 2: i++; } ) { ... }
) verwenden - das ist nicht möglich. Es ist keine Aussage. Stattdessen ist es definiert alsfor ( {<expression>}? ; {<expression>}? ; {<expression>}? ) <statement>
int i = 0
ist definitiv kein Ausdruck. Der Regelsatz, der einen Ausdruck beschreibt, ist ziemlich komplex, wenn man bedenkt, was einen Ausdruck ausmachen kann, aber das KonstruktTYPE NAME = EXPRESSION
stimmt mit keiner dieser Regeln überein.