Dans de nombreuses langues (une large liste, de C à JavaScript):
,
arguments séparés (par exemple func(a, b, c)
), tandis que;
instructions séquentielles distinctes (par exemple instruction1; instruction2; instruction3
).Alors pourquoi ce mappage est-il inversé dans les mêmes langues pour pour les boucles:
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'est-à-dire init
, condition
, increment
) se comportent plus comme des arguments d'une fonction qu'un séquence d'instructions.
Est-ce pour des raisons historiques/une convention, ou existe-t-il une bonne justification pour l'échange de ,
Et ;
En boucles?
Alors pourquoi dans les mêmes langues un tel mappage est inversé pour les boucles for.
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 le même avec le même, il n'y a donc pas de mappage et aucun argument solide pour un mappage cohérent basé sur la cohérence sémantique.
Alors pourquoi ne pas faire l'inverse?
Eh bien, je pense que les raisons viennent du sens "naturel" de ,
et ;
. Dans la langue écrite anglaise, un point-virgule est une coupure "plus forte" qu'une virgule, et le glyphe pour le point-virgule est plus visible qu'une virgule. Ces deux choses se combinent pour rendre l'arrangement actuel (pour moi!) Plus naturel.
Mais la seule façon de savoir avec certitude pourquoi le choix de la syntaxe a été fait serait que les concepteurs C puissent nous dire ce qu'ils pensaient en 1970. Je doute qu'ils aient une mémoire claire des décisions techniques prises aussi loin dans le temps.
Est-ce pour des raisons historiques/une convention
Je ne connais aucun langage avant C qui utilise une syntaxe de type C pour les boucles "for":
Donal Fellows note que BCPL et B n'avaient pas de construction équivalente.
Les équivalents FORTRAN, COBOL et ALGOL-60 (et Pascal) étaient moins expressifs et avaient des syntaxes qui ne ressemblaient pas à la syntaxe C "for".
Mais des langages comme C, C++ et Java qui sont venus après C empruntent tous clairement leur syntaxe "for" à C.
Nous écrivons des boucles comme:
for(x = 0; x < 10; x++)
Le langage aurait pu être défini pour que les boucles ressemblent à:
for(x = 0, x < 10, x++)
Cependant, pensez à la même boucle implémentée à l'aide d'une boucle while:
x = 0;
while(x < 10)
{
x++;
}
Notez que le x=0
et x++
sont des instructions, terminées par des points-virgules. Ce ne sont pas des expressions comme vous le feriez dans un appel de fonction. Les points-virgules sont utilisés pour séparer les instructions, et puisque 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 pour une fonction. Les deuxième et troisième sont évalués à plusieurs reprises. C'est vrai qu'ils ne sont pas une séquence, mais ce ne sont pas non plus des arguments de fonction.
De plus, le fait que vous puissiez utiliser des virgules pour avoir plusieurs instructions dans la boucle for est en fait quelque chose que vous pouvez faire en dehors de la boucle for.
x = 0, y= 3;
est une instruction parfaitement valide 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 caractéristique spéciale de la boucle for.
En C et C++, c'est l'opérateur virgule, pas seulement une virgule.
La grammaire d'une boucle for
est quelque chose comme
for ([pre-expression]; [terminate-condition]; [increment-expression]) body-expression
Dans le cas de votre question:
pre-expression -> init1, init2
terminate-condition -> condition
increment-expression -> inc1, inc2
Notez que l'opérateur virgule vous permet d'effectuer plusieurs actions dans une seule instruction (comme le compilateur le voit). Si votre suggestion était mise en œuvre, il y aurait une ambiguïté dans la grammaire quant au moment où le programmeur avait l'intention d'écrire une instruction d'opérateur virgule ou un séparateur.
En bref, ;
signifie la fin d'une instruction. Une boucle for
est un mot clé suivi d'une liste d'instructions facultatives entourées de ()
. L'instruction virgule-opérateur permet d'utiliser ,
en une seule instruction.
Il n'y a pas de renversement conceptuel.
Les points-virgules en C représentent des divisions plus importantes que les 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 C pour les boucles 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 fonction.
C'est peut-être quelque chose de spécifique pour C/C++, mais je poste cette réponse, car la syntaxe des langages que vous avez décrits est principalement influencée par la syntaxe C.
Outre que les questions précédemment répondues sont vraies, 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 surcharge . L'utilisation d'un opérateur point-virgule (operator;()
) rendrait peut-être plus difficile l'écriture de compilateurs, car le point-virgule est le terminateur de l'expression axiomatique.
Ce qui rend cette interférence est le fait que la virgule est largement utilisée comme séparateur dans toute la langue. Il semble que l'opérateur virgule soit une exception, qui est principalement utilisé pour faire fonctionner les boucles for
- avec plusieurs conditions, alors quel est le problème?
En fait, le operator,
est conçu pour faire la même chose que dans les définitions, les listes d'arguments, etc.: il a été construit en expressions distinctes - quelque chose de la construction syntaxique ,
ne peut pas faire. Il ne peut que séparer ce qui a été défini dans la norme.
Cependant, le point-virgule ne se sépare pas - il se termine . Et c'est aussi ce qui nous ramène à la question d'origine:
for (int a = 0, float b = 0.0f; a < 100 && b < 100.0f; a++, b += 1.0f)
printf("%d: %f", a, b);
La virgule sépare les expressions dans les trois parties de la boucle, tandis que le point-virgule termine une partie (initialisation, condition ou après coup) de la définition de la boucle.
Les nouveaux langages de programmation (comme C #) peuvent ne pas permettre de surcharger l'opérateur virgule, mais ils ont très probablement conservé la syntaxe, car le changer semble quelque peu contre nature.
Pour moi, ils sont utilisés dans un sens moins similaire à leur sens linguistique. Les virgules sont utilisées avec des listes et des points-virgules avec des parties plus séparées.
Dans 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.
Dans for ( init1, init2; condition; inc1, inc2 )
, nous avons trois parties distinctes - une liste d'initialisations, une condition et une liste d'expressions d'incrémentation.
La façon la plus simple de le voir est la suivante:
for(x = 0; x < 10; x++)
est:
for(
x = 0;
x < 10;
x++
)
En d'autres termes, ce truc x = 0 est en fait une instruction/des instructions plutôt qu'un paramètre. Vous y insérez une déclaration. Ils sont donc séparés par un point-virgule.
En fait, il n'y a aucun moyen qu'ils soient séparés par une virgule. Quand la dernière fois que vous insérez des choses comme x <10 comme paramètre? Vous faites cela si vous voulez une fois x x 10 sur l'ordinateur et insérez le résultat de cette opération comme 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 passage de la boucle. Voilà donc une instruction.
x ++ est certainement une autre instruction.
Ce sont toutes des instructions. Ils sont donc séparés par un point-virgule.