Em vários idiomas (uma lista ampla, de C a JavaScript):
- vírgulas
,
separam argumentos (por exemplofunc(a, b, c)
), enquanto - ponto e vírgula
;
separam instruções seqüenciais (por exemploinstruction1; instruction2; instruction3
).
Então, por que esse mapeamento é revertido nos mesmos idiomas para loops for :
for ( init1, init2; condition; inc1, inc2 )
{
instruction1;
instruction2;
}
em vez de (o que me parece mais natural)
for ( init1; init2, condition, inc1; inc2 )
{
instruction1;
instruction2;
}
?
Claro, for
é (geralmente) não é uma função, mas os argumentos (ou seja init
, condition
, increment
) se comportam mais como argumentos de uma função do que uma seqüência de instruções.
Não é devido a razões históricas / uma convenção, ou é uma boa razão para a troca de ,
e ;
em loops?
programming-languages
syntax
loops
Piotr Migdal
fonte
fonte
;
não usamos|
?" (ou Por que usamos 'else', não 'caso contrário'? )), que não é o caso de um idioma, mas de um grande número deles. Uma resposta que, por exemplo, "foi feita em C como um atalho para o loop while (e várias declarações para inc foram pensadas apenas mais tarde), e as pessoas não quiseram alterá-lo para evitar a irritação dos programadores" seria perfeitamente aceitável.Respostas:
Tecnicamente, o mapeamento não é "revertido".
Na realidade, o que temos aqui é um contexto sintático diferente, onde os mesmos símbolos estão sendo usados de maneira diferente. Não estamos comparando like com like, portanto não há mapeamento e nenhum argumento forte para um mapeamento consistente com base na consistência semântica.
Então, por que não fazer o contrário?
Bem, acho que as razões vêm do significado "natural" de
,
e;
. No idioma escrito em inglês, um ponto e vírgula é uma pausa "mais forte" que uma vírgula, e o glifo para ponto e vírgula é mais visível que uma vírgula. Essas duas coisas se combinam para fazer com que o arranjo atual pareça (para mim!) Ser mais natural.Mas a única maneira de saber ao certo por que a escolha da sintaxe foi feita seria se os designers de C pudessem nos dizer o que estavam pensando em 1970. Duvido que eles tenham uma clara memória de decisões técnicas tomadas tão longe no tempo.
Não tenho conhecimento de nenhum idioma antes de C que usasse uma sintaxe semelhante a C para loops "for":
Donal Fellows observa que BCPL e B não tinham uma construção equivalente.
Os equivalentes FORTRAN, COBOL e Algol-60 (e Pascal) eram menos expressivos e tinham sintaxes que não se assemelhavam à sintaxe C "para".
Mas linguagens como C, C ++ e Java que vieram depois de C claramente emprestam sua sintaxe "for" de C.
fonte
,
vs;
) é (quebra mais fraca vs. Ainda para mim, não é óbvio se os argumentos ou declarações precisam de interrupções mais fortes (como em muitos casos, para uma sequência de declarações, as interrupções estão implícitas (consulte, por exemplo, JavaScript (por exemploi++[line break]j++
))), mas pelo menos agora entendi o porquê da convenção atual não é "obviamente revertido".FOR i = e1 TO e2 BY e3 DO c
(expressões e1..e3, comando c), que mais se assemelha à sintaxe do BASIC. Origemfor
sintaxe foi introduzida em C (não estava em B ou BCPL).Escrevemos loops como:
O idioma poderia ter sido definido para que os loops parecessem:
No entanto, pense no mesmo loop implementado usando um loop while:
Observe que as instruções
x=0
ex++
são terminadas por ponto e vírgula. Eles não são expressões como você teria em uma chamada de função. Ponto-e-vírgula são usados para separar instruções, e como dois dos três elementos em um loop for são instruções, é isso que é usado lá. Um loop for é apenas um atalho para um loop while.Além disso, os argumentos realmente não agem como argumentos para uma função. O segundo e o terceiro são avaliados repetidamente. É verdade que eles não são uma sequência, mas também não são argumentos de função.
Além disso, o fato de que você pode usar vírgulas para ter várias instruções no loop for é realmente algo que você pode fazer fora do loop for.
é uma declaração perfeitamente válida mesmo fora de um loop for. Não conheço nenhum uso prático fora do loop for. Mas o ponto é que vírgulas sempre subdividem declarações; não é uma característica especial do loop for.
fonte
x = 0; y = 0;
e (dentro do colchete)x++; y++;
...;
é natural para uma sequência de afirmações , não necessariamente separando quaisquer afirmações (será que o gosto é diferente?). E no actual uma convenção, ocasionalmente, acaba com a separação seqüências de declarações com vírgulas de qualquer maneira ...(foo)?bar++, qux++:bletch
--- Onde você deseja que a?:
expressão faça duas coisas em vez de apenas uma. O valor de retorno sefoo
for verdadeiro équx
, mas ambosbar
equx
são incrementados.Em C e C ++, esse é o operador de vírgula, não apenas uma vírgula.
A gramática de um
for
loop é algo comoNo caso de sua pergunta:
Observe que o operador de vírgula permite executar várias ações em uma instrução (como o compilador vê). Se sua sugestão foi implementada, haveria uma ambiguidade na gramática sobre quando o programador pretendia escrever uma declaração de operador de vírgula ou um separador.
Em resumo,
;
significa o fim de uma declaração. Umfor
loop é uma palavra-chave seguida por uma lista de instruções opcionais cercadas por()
. A instrução vírgula-operador permite o uso de,
em uma única instrução.fonte
for
loop permite explicitamente uma declaração (declaração) como sua primeira parte. (C ++ permitiu declarações com função intermediária, em oposição ao seu predecessor C89). Você não pode generalizar essas declarações entre idiomas, mesmo em dois idiomas tão próximos quanto C e C ++.for ( {<expression>}? ; {<expression>}? ; {<expression>}? ) <statement>
para C efor ( for-init-statement; conditionopt ; expressionopt ) statement
de C ++ --- O ';' não significa apenas um terminador de instrução. Um loop for não é seguido por instruções incluídas em ().Não há reversão conceitual.
O ponto e vírgula em C representa mais divisões principais do que vírgulas. Eles separam declarações e declarações.
As principais divisões no loop for são que existem três expressões (ou uma declaração e duas expressões) e um corpo.
As vírgulas que você vê em C para loops não fazem parte da sintaxe do loop for especificamente. São apenas manifestações do operador de vírgula.
Vírgulas são os principais separadores entre argumentos em chamadas de função e entre parâmetros em declarações de função, mas ponto e vírgula não é usado. O loop for é uma sintaxe especial; não tem nada a ver com funções ou chamadas de função.
fonte
Talvez isso seja algo específico para C / C ++, mas eu posto esta resposta, porque a sintaxe dos atrasos que você descreveu é influenciada principalmente pela sintaxe C.
Além das perguntas respondidas anteriormente serem verdadeiras, do ponto de vista técnico, também porque em C (e C ++) a vírgula é realmente um operador , que você pode até sobrecarregar . Usar um ponto-e-vírgula-operador (
operator;()
) possivelmente tornaria mais difícil escrever compiladores, pois o ponto-e-vírgula é o terminador de expressões axiomáticas.O que torna isso interessante é o fato de que a vírgula é amplamente usada como separador em todo o idioma. Parece que o operador de vírgula é uma exceção, usado principalmente para obter
for
loops com várias condições funcionando, então qual é o problema?De fato, ele
operator,
é construído para fazer o mesmo que em definições, listas de argumentos e assim por diante: Ele foi construído para separar expressões - algo que a construção sintática,
não pode fazer. Só pode separar o que foi definido no padrão.No entanto, o ponto e vírgula não se separa - ele termina . E é também isso que nos leva de volta à pergunta original:
A vírgula separa as expressões nas três partes do loop, enquanto o ponto e vírgula termina uma parte (inicialização, condição ou reflexão posterior) da definição do loop.
As linguagens de programação mais recentes (como C #) podem não permitir sobrecarregar o operador de vírgula, mas elas provavelmente mantiveram a sintaxe, porque a alteração parece algo antinatural.
fonte
for
declaração, o;
símbolo é usado claramente como um separador. Separa as três partes sintáticas da declaração. Não existe um terceiro ponto e vírgula para "finalizar" a lista de expressões progressivas. É finalizado por um token diferente -)
.Para mim, eles usam um significado menos parecido com o sentido linguístico. Vírgulas são usadas com listas e ponto e vírgula com partes mais separadas.
Em
func(a, b, c)
nós temos uma lista de argumentos.instruction1; instruction2; instruction3
talvez seja uma lista, mas uma lista de instruções separadas e independentes.Enquanto
for ( init1, init2; condition; inc1, inc2 )
temos três partes separadas - uma lista de inicializações, uma condição e uma lista de expressões de incremento.fonte
A maneira mais fácil de ver isso é a seguinte:
é:
Em outras palavras, essas coisas x = 0 são na verdade uma declaração / instruções, e não um parâmetro. Você insere uma declaração lá. Portanto, eles são separados por ponto e vírgula.
De fato, não há como eles serem separados por vírgula. Quando a última vez que você insere itens como x <10 como parâmetro? Faça isso se desejar computador x <10 uma vez e insira o resultado dessa operação como parâmetro. Portanto, no mundo das vírgulas, você colocaria x <10 se desejar passar o valor de x <0 para uma função.
Aqui você especifica que o programa deve verificar x <10 toda vez que o loop for passado. Então isso é uma instrução.
x ++ é definitivamente outras instruções.
Essas são todas as instruções. Então eles são separados por ponto e vírgula.
fonte
for
switch
oureturn
dentro da definição do loop for (iefor(int i = 0; if(i > 1024) { return; } ; switch (i % 3) { case 0; case 1: i++; case 2: i++; } ) { ... }
) --- você não pode. Não é uma afirmação. Em vez disso, é definido comofor ( {<expression>}? ; {<expression>}? ; {<expression>}? ) <statement>
int i = 0
definitivamente NÃO é uma expressão. O conjunto de regras que descrevem uma expressão é bastante complexo, considerando o que pode constituir uma expressão, mas a construçãoTYPE NAME = EXPRESSION
não corresponde a nenhuma dessas regras.