Por que os pontos e vírgulas são trocados por loops?

49

Em muitos idiomas (uma lista ampla, de C a JavaScript):

  • commas , argumentos separados (por exemplo, func(a, b, c) ), enquanto
  • ponto-e-vírgula ; instruções sequenciais separadas (por exemplo, instruction1; instruction2; instruction3 ).

Então, por que esse mapeamento é invertido nas mesmas linguagens para para loops :

for ( init1, init2; condition; inc1, inc2 )
{
    instruction1;
    instruction2;
}

em vez de (o que parece mais natural para mim)

for ( init1; init2, condition, inc1; inc2 )
{
    instruction1;
    instruction2;
}

?

Claro, for não é (geralmente) uma função, mas os argumentos (por exemplo, init , condition , increment ) se comportam mais como argumentos de uma função do que uma sequência de instruções.

É por razões históricas / uma convenção, ou há uma boa razão para o intercâmbio de , e ; em loops?

    
por Piotr Migdal 21.04.2013 / 23:16
fonte

7 respostas

18

So why in the same languages such mapping is reversed for for loops.

Tecnicamente, o mapeamento não é "revertido".

  • As coisas separadas por vírgulas não são parâmetros. Em (pelo menos) C ++ e Java, eles podem ser declarações, portanto nem sequer são expressões.
  • As coisas separadas por ponto-e-vírgula também não são declarações (únicas).

Na realidade, o que temos aqui é um contexto sintático diferente, onde os mesmos símbolos estão sendo usados de forma diferente. Nós não estamos comparando com like, então não há mapeamento, e nenhum argumento strong para um mapeamento consistente baseado 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 ; . Na linguagem escrita em inglês, um ponto e vírgula é uma quebra "mais strong" do que uma vírgula, e o glifo para ponto-e-vírgula é mais visível do 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 com certeza por que a escolha da sintaxe foi feita seria se os projetistas de C pudessem nos dizer o que estavam pensando em 1970. Eu duvido que eles tenham uma memória clara das decisões técnicas feitas no passado.

Is it due to historical reasons / a convention

Não tenho conhecimento de nenhum idioma antes de C que usou uma sintaxe semelhante a C para loops "for":

  • Donal Fellows observa que BCPL e B não tinham uma construção equivalente.

  • Os equivalentes de FORTRAN, COBOL e Algol-60 (e Pascal) foram menos expressivos e tinham sintaxes que não se assemelham à sintaxe C "para".

Mas linguagens como C, C ++ e Java que vieram depois de C claramente emprestam sua sintaxe "for" de C.

    
por 22.04.2013 / 01:02
fonte
60

Nós escrevemos loops como:

 for(x = 0; x < 10; x++)

A linguagem poderia ter sido definida para que os loops parecessem:

 for(x = 0, x < 10, x++)

No entanto, pense no mesmo loop implementado usando um loop while:

 x = 0;
 while(x < 10)
 {
     x++;
 }

Observe que as instruções x=0 e x++ 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írgulas são usados para separar instruções e, como dois dos três elementos em um loop for são instruções, é o que é usado lá. Um loop for é apenas um atalho para um loop while.

Além disso, os argumentos não agem como argumentos para uma função. O segundo e terceiro são repetidamente avaliados. É 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 você poder usar vírgulas para ter várias instruções no loop for é algo que pode ser feito fora do loop for.

x = 0, y= 3;

é uma afirmação perfeitamente válida, mesmo fora de um loop for. Eu não sei de nenhum uso prático fora do loop for embora. Mas o ponto é que as vírgulas sempre subdividem instruções; não é uma característica especial do loop for.

    
por 21.04.2013 / 23:38
fonte
15

Em C e C ++, este é o operador de vírgula, não apenas uma vírgula.

A gramática para um loop for é algo como

for ([pre-expression]; [terminate-condition]; [increment-expression]) body-expression

No caso da sua pergunta:

pre-expression -> init1, init2
terminate-condition -> condition
increment-expression -> inc1, inc2

Observe que o operador-vírgula permite executar várias ações em uma instrução (conforme o compilador a vê). Se sua sugestão fosse implementada, haveria uma ambigüidade na gramática quanto ao momento em que o programador pretendia escrever uma declaração de operador de vírgula ou um separador.

Em suma, ; significa o final de uma declaração. Um for loop é uma palavra-chave seguida por uma lista de instruções opcionais cercadas por () . A instrução comma-operator permite o uso de , em uma única instrução.

    
por 22.04.2013 / 01:44
fonte
8

Não há reversão conceitual.

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 três expressões (ou uma declaração e duas expressões) e um corpo.

As vírgulas que você vê nos loops C não fazem parte da sintaxe do loop for especificamente. Eles são apenas manifestações do operador de vírgula.

Vírgulas são separadores principais entre argumentos em chamadas de função e entre parâmetros em declarações de função, mas ponto e vírgula não são usados. O loop for é uma sintaxe especial; não tem nada a ver com funções ou chamadas de função.

    
por 22.04.2013 / 03:45
fonte
2

Talvez isso seja algo específico para C / C ++, mas eu postei essa resposta, porque a sintaxe dos lagnuages que você descreveu é principalmente influenciada pela C-Sintaxe.

Além das perguntas respondidas anteriormente serem verdadeiras, do ponto de vista técnico, isso também acontece porque em C (e C ++) a vírgula é na verdade uma operador , que você pode até mesmo sobrecarga . Usar um operador de ponto-e-vírgula ( operator;() ) possivelmente tornaria mais difícil escrever compiladores, uma vez que o ponto-e-vírgula é o terminador de expressão axiomática.

O que torna este intersting é o fato de que a vírgula é amplamente usada como separador em toda a linguagem. Parece que o operador vírgula é uma exceção, que é usado principalmente para obter for -loops com várias condições funcionando, então qual é o problema?

Na verdade, o operator, é construído para fazer a mesma coisa em definições, listas de argumentos e assim por diante: Foi construído para expressões separadas - algo que a construção sintática , não pode Faz. Só pode separar o que foi definido no padrão.

No entanto, o ponto-e-vírgula não se separa - termina . E isso também é o que nos leva de volta à pergunta original:

for (int a = 0, float b = 0.0f; a < 100 && b < 100.0f; a++, b += 1.0f)
    printf("%d: %f", a, b);

A vírgula separa as expressões nas três partes do loop, enquanto o ponto-e-vírgula encerra uma parte (inicialização, condição ou reflexão tardia) da definição de loop.

Linguagens de programação mais recentes (como o C #) podem não permitir a sobrecarga do operador-vírgula, mas elas provavelmente mantiveram a sintaxe, porque a mudança parece algo pouco natural.

    
por 22.04.2013 / 12:38
fonte
0

Para mim, eles são usados com um significado menos semelhante ao seu sentido lingüístico. As vírgulas são usadas com listas e ponto-e-vírgulas com partes separadas.

Em func(a, b, c) , temos uma lista de argumentos.

instruction1; instruction2; instruction3 é talvez uma lista, mas uma lista de instruções separadas e independentes.

Enquanto em 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.

    
por 22.04.2013 / 01:26
fonte
0

A maneira mais fácil de ver é o seguinte:

for(x = 0; x < 10; x++)

é:

for(
x = 0;
x < 10;
x++
)

Em outras palavras, aqueles x = 0 thingy são na verdade uma instrução / instruções em vez de um parâmetro. Você insere uma declaração lá. Por isso, eles são separados por ponto e vírgula.

Na verdade, não há como eles serem separados por vírgula. Quando foi a última vez que você inseriu coisas como x < 10 como um parâmetro? Você faz isso se quiser computador x < 10 uma vez e insere o resultado dessa operação como parâmetro. Então, no mundo da vírgula você colocaria x < 10 se quiser 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 outra instrução.

Essas são todas as instruções. Então eles são separados por ponto e vírgula.

    
por 22.04.2013 / 06:46
fonte