Dans de nombreuses langues (une liste étendue, du C au JavaScript):
- virgules
,
séparer les arguments (par exemplefunc(a, b, c)
), tandis que - les points-virgules
;
séparent les instructions séquentielles (par exempleinstruction1; instruction2; instruction3
).
Alors, pourquoi ce mappage est-il inversé dans les mêmes langues pour les boucles for :
for ( init1, init2; condition; inc1, inc2 )
{
instruction1;
instruction2;
}
au lieu de (ce qui me semble plus naturel)
for ( init1; init2, condition, inc1; inc2 )
{
instruction1;
instruction2;
}
?
Bien sûr, for
n’est (généralement) pas une fonction, mais les arguments (c. init
-à- d . condition
, increment
) Se comportent davantage comme des arguments d’une fonction que comme une séquence d’instructions.
Est - ce pour des raisons historiques / une convention, ou est - il une bonne raison pour l'échange de ,
et ;
dans les boucles?
programming-languages
syntax
loops
Piotr Migdal
la source
la source
;
pas|
?" (ou Pourquoi utilisons-nous "sinon"? " ) qui n'est pas le cas pour une langue, mais pour un grand nombre d'entre elles. Une réponse, par exemple, "cela a été fait en C comme raccourci pour la boucle While (et plusieurs énoncés pour inca été pensé que plus tard), et les gens ne voulaient pas le changer pour éviter l'irritation des programmeurs" serait parfaitement acceptable.Réponses:
Techniquement, le mappage n'est pas "inversé".
En réalité, nous avons ici un contexte syntaxique différent où les mêmes symboles sont utilisés différemment. Nous ne comparons pas ce qui est semblable, il n'y a donc pas de mappage ni d'argument fort en faveur d'un mappage cohérent basé sur la cohérence sémantique.
Alors pourquoi ne pas le faire dans le sens inverse?
Eh bien, je pense que les raisons viennent du sens "naturel" de
,
et;
. En anglais, un point-virgule est une coupure "plus forte" qu'une virgule et le glyphe de point-virgule est plus visible qu'une virgule. Ces deux choses concourent à rendre l’arrangement actuel (pour moi!) Plus naturel.Mais le seul moyen de savoir avec certitude pourquoi le choix de la syntaxe a été choisi serait que les concepteurs C puissent nous dire ce qu’ils pensaient en 1970. Je doute qu'ils se souviennent clairement des décisions techniques prises jusque-là.
Je ne connais pas de langage avant C utilisant une syntaxe de type C pour les boucles "pour":
Donal Fellows note que BCPL et B n’avaient pas de structure équivalente.
Les équivalents FORTRAN, COBOL et Algol-60 (et Pascal) étaient moins expressifs et leurs syntaxes ne ressemblaient pas à la syntaxe C "pour".
Mais les langages comme C, C ++ et Java qui ont succédé à C empruntent tous clairement leur syntaxe "pour" à C.
la source
,
vs;
) est (coupure plus faible ou plus forte), plutôt que (séparateur de tuple contre séquence), non? Pour moi, il n’est pas évident de savoir si les arguments ou les déclarations nécessitent des ruptures plus fortes (comme dans de nombreux cas pour une séquence de déclarations, les ruptures sont implicites (voir, par exemple, JavaScript (exemplei++[line break]j++
))), mais au moins, je comprends maintenant pourquoi la convention actuelle n'est pas "évidemment inversé".FOR i = e1 TO e2 BY e3 DO c
(expressions e1..e3, commande c), qui ressemble davantage à la syntaxe de BASIC. Sourcefor
syntaxe a été introduite en C (ce n'était pas en B ou BCPL).Nous écrivons des boucles comme:
Le langage aurait pu être défini de manière à ce que les boucles ressemblent à:
Cependant, pensez à la même boucle implémentée en utilisant une boucle while:
Notez que les instructions
x=0
andx++
sont terminées par des points-virgules. Ce ne sont pas des expressions comme celles que vous auriez dans un appel de fonction. Les points-virgules sont utilisés pour séparer des instructions, et comme deux des trois éléments d'une boucle for sont des instructions, c'est ce qui est utilisé ici. Une boucle for n'est qu'un raccourci pour une telle boucle while.De plus, les arguments n'agissent pas vraiment comme des arguments d'une fonction. Les deuxième et troisième sont évalués à plusieurs reprises. Il est vrai qu'ils ne sont pas une séquence, mais ils ne sont pas non plus des arguments de fonction.
En outre, le fait que vous puissiez utiliser des virgules pour avoir plusieurs instructions dans la boucle for est en réalité quelque chose que vous pouvez faire en dehors de la boucle for.
est une déclaration parfaitement valable même en dehors d'une boucle for. Je ne connais cependant aucune utilisation pratique en dehors de la boucle for. Mais le fait est que les virgules subdivisent toujours les instructions; ce n'est pas une particularité de la boucle for.
la source
x = 0; y = 0;
et (entre les crochets)x++; y++;
...;
est naturel pour une séquence d’énoncés , pas nécessairement en séparant les énoncés (c’est pourquoi les goûts diffèrent-ils?). Et dans la convention actuelle, on finit parfois par séparer des séquences d'instructions avec des virgules ...(foo)?bar++, qux++:bletch
--- Et si vous voulez que l'?:
expression fasse deux choses plutôt qu'une seule. La valeur de retour sifoo
true estqux
, mais les deuxbar
etqux
sont incrémentés.En C et C ++, il s'agit de l'opérateur de virgule, pas simplement d'une virgule.
La grammaire pour une
for
boucle est quelque chose commeDans le cas de votre question:
Notez que l'opérateur de virgule vous permet d'effectuer plusieurs actions dans une instruction (comme le compilateur le voit). Si votre suggestion était mise en œuvre, la grammaire serait ambiguë quant au moment où le programmeur a l'intention d'écrire une instruction opérateur par virgule ou un séparateur.
En bref,
;
signifie la fin d'une déclaration. Unefor
boucle est un mot-clé suivi d'une liste d'instructions facultatives entourées par()
. L'instruction virgule-opérateur permet l'utilisation de,
dans une seule instruction.la source
for
boucle autorise explicitement une déclaration (déclaration) en tant que première partie. (C ++ autorisait les déclarations de moyenne fonction, contrairement à son prédécesseur C89). Vous ne pouvez pas généraliser de telles instructions à travers les langages, même pour 2 langages aussi proches que C et C ++.for ( {<expression>}? ; {<expression>}? ; {<expression>}? ) <statement>
pour C etfor ( for-init-statement; conditionopt ; expressionopt ) statement
pour C ++ --- Le « ; » ne signifie pas seulement un terminateur de déclaration. Une boucle for n'est pas suivie d'instructions entre ().Il n'y a pas d'inversion conceptuelle.
Les points-virgules en C représentent plus de divisions principales que de virgules. Ils séparent les déclarations et les déclarations.
Les principales divisions de la boucle for sont qu'il existe trois expressions (ou une déclaration et deux expressions) et un corps.
Les virgules que vous voyez dans les boucles for for ne font pas spécifiquement partie de la syntaxe de la boucle for. Ce ne sont que des manifestations de l'opérateur virgule.
Les virgules sont des séparateurs majeurs entre les arguments dans les appels de fonction et entre les paramètres dans les déclarations de fonction, mais les points-virgules ne sont pas utilisés. La boucle for est une syntaxe spéciale; cela n'a rien à voir avec des fonctions ou des appels de fonctions.
la source
C'est peut-être quelque chose de spécifique pour C / C ++, mais je poste cette réponse, car la syntaxe des lagnages que vous avez décrits est principalement influencée par la syntaxe C.
En plus des réponses précédentes aux questions précédentes, d’un point de vue technique, c’est aussi parce qu’en C (et C ++), la virgule est en fait un opérateur , que vous pouvez même surcharger . L'utilisation d'un opérateur point-virgule (
operator;()
) rendrait probablement plus difficile l'écriture de compilateurs, car le point-virgule est le terminateur d'expression axiomatique.Ce qui rend ce intersting est le fait que la virgule est largement utilisé comme seperator partout dans la langue. Il semble que l'opérateur de virgule soit une exception, principalement utilisée pour faire fonctionner les
for
boucles avec plusieurs conditions, alors quel est le problème?En fait, il
operator,
est conçu pour faire la même chose que dans les définitions, les listes d'arguments, etc.: Il a été construit pour séparer les expressions - ce que la construction syntaxique,
ne peut pas faire. Il ne peut séparer que ce qui a été défini dans la norme.Cependant, le point-virgule ne sépare pas - il se termine . Et c’est aussi ce qui nous ramène à la question initiale:
La virgule sépare les expressions dans les trois parties de la boucle, tandis que le point-virgule termine une partie (initialisation, condition ou réflexion ultérieure) de la définition de la boucle.
Les nouveaux langages de programmation (tels que C #) ne permettent peut-être pas de surcharger l'opérateur virgule, mais ils conservent probablement la syntaxe, car leur modification semble quelque peu anormale.
la source
for
déclaration, le;
symbole est clairement utilisé comme séparateur. Il sépare les 3 parties syntaxiques de la déclaration. Il n'y a pas de 3ème point-virgule pour "terminer" la liste des expressions progressives. Il se termine par un autre jeton -)
.Pour moi, ils sont utilisés de manière moins semblable à leur sens linguistique. Les virgules sont utilisées avec des listes et des points-virgules avec des parties plus séparées.
En
func(a, b, c)
nous avons une liste d'arguments.instruction1; instruction2; instruction3
est peut-être une liste mais une liste d'instructions séparées et indépendantes.Alors que dans
for ( init1, init2; condition; inc1, inc2 )
nous avons trois parties distinctes - une liste des initialisations, une condition et une liste d'expressions incrément.la source
Le moyen le plus simple de le voir est le suivant:
est:
En d'autres termes, ces x = 0 thingy sont en fait une instruction / des instructions plutôt qu'un paramètre. Vous insérez une déclaration ici. Ils sont donc séparés par un point-virgule.
En fait, il n’ya aucun moyen de les séparer par une virgule. Quand insérez-vous des éléments comme x <10 en tant que paramètre? Vous faites cela si vous voulez utiliser l’ordinateur x <10 une fois et insérer le résultat de cette opération en tant que paramètre. Donc, dans le monde des virgules, vous mettriez x <10 si vous voulez transmettre la valeur de x <0 à une fonction.
Ici, vous spécifiez que le programme doit vérifier x <10 à chaque fois que la boucle est passée. Donc, c'est une instruction.
x ++ est certainement une autre instruction.
Ce sont toutes des instructions. Donc, ils sont séparés par un point-virgule.
la source
for
switch
oureturn
à l' intérieur de la définition de la boucle for (c'est-à-direfor(int i = 0; if(i > 1024) { return; } ; switch (i % 3) { case 0; case 1: i++; case 2: i++; } ) { ... }
) --- vous ne pouvez pas. Ce n'est pas une déclaration. Au lieu de cela, il est défini commefor ( {<expression>}? ; {<expression>}? ; {<expression>}? ) <statement>
int i = 0
n'est certainement pas une expression. L'ensemble de règles décrivant une expression est assez complexe, considérant ce qui peut constituer une expression, mais la constructionTYPE NAME = EXPRESSION
ne correspond à aucune de ces règles.