Eu estava trabalhando com um novo desenvolvedor de C ++ há algum tempo quando ele fez a pergunta: "Por que nomes de variáveis não podem começar com números?"
Não consegui encontrar uma resposta, exceto que alguns números podem conter texto (123456L, 123456U) e isso não seria possível se os compiladores estivessem pensando que tudo com alguma quantidade de caracteres alfa era um nome variável.
Essa foi a resposta certa? Existem mais razões?
string 2BeOrNot2Be = "that is the question"; // Why won't this compile?
0
que empurra 0 para a pilha. outro é0=
que verifica se 0 está na pilha.Respostas:
Porque então uma sequência de dígitos seria um identificador válido e também um número válido.
fonte
A
-F
e terminavam comh
. Tropecei na primeira vez em que tentei definir um rótulo para apontar para os dados da música da Invenção 13 de Bach em duas partes (nome lógico?Bach
).Bem, pense sobre isso:
O que é uma? 2.0? ou 42?
Dica, se você não conseguir, d depois de um número significa o número antes que seja um literal duplo
fonte
d
não é um sufixo literal flutuante válido em C ++. Literais flutuantes são duplos por padrão, você pode usarf
oul
se precisar de um flutuante ou um longo duplo literal.É uma convenção agora, mas começou como um requisito técnico.
Antigamente, analisadores de idiomas como FORTRAN ou BASIC não exigiam o uso de espaços. Então, basicamente, o seguinte é idêntico:
e
Agora, suponha que prefixos numéricos sejam permitidos. Como você interpretaria isso?
Como
ou como
ou como
Então, isso foi feito ilegal.
fonte
DO 10 I=1,50
pode ser analisado ambiguamente comoDO1 0I=1,50
[aliás, se alguém usar um ponto em vez de vírgula, a instrução se tornará uma atribuição a um variável de ponto flutuante denominadaDO10I
.Porque o retorno é evitado na análise lexical durante a compilação. Uma variável como:
o compilador saberá que é um identificador imediatamente quando encontrar a letra 'A'.
No entanto, uma variável como:
O compilador não será capaz de decidir se é um número ou identificador até atingir 'a' e, portanto, precisa voltar atrás.
fonte
Os compiladores / analisadores / analisadores lexicais foram muito, muito tempo atrás para mim, mas acho que me lembro de haver dificuldade em determinar sem ambigüidade se um caractere numérico na unidade de compilação representava um literal ou um identificador.
Idiomas em que o espaço é insignificante (como ALGOL e FORTRAN original, se bem me lembro) não podiam aceitar números para iniciar identificadores por esse motivo.
Isso remonta - antes de notações especiais para indicar armazenamento ou base numérica.
fonte
Concordo que seria útil permitir que os identificadores começassem com um dígito. Uma ou duas pessoas mencionaram que você pode contornar essa restrição acrescentando um sublinhado ao seu identificador, mas isso é realmente feio.
Acho que parte do problema vem de literais numéricos como 0xdeadbeef, que dificultam a criação de regras fáceis de lembrar para identificadores que podem começar com um dígito. Uma maneira de fazer isso pode ser permitir qualquer coisa que corresponda a [A-Za-z _] + que NÃO seja uma palavra-chave ou literal de número. O problema é que isso levaria a coisas estranhas como 0xdeadpork, mas não 0xdeadbeef. Por fim, acho que devemos ser justos com todas as carnes: p.
Quando aprendi C pela primeira vez, lembro que as regras para nomes de variáveis eram arbitrárias e restritivas. Pior de tudo, eles eram difíceis de lembrar, então desisti de tentar aprendê-los. Eu apenas fiz o que parecia certo, e funcionou muito bem. Agora que aprendi muito mais, não parece tão ruim e finalmente aprendi direito.
fonte
É provável que tenha sido uma decisão tomada por alguns motivos: quando você estiver analisando o token, precisará analisar apenas o primeiro caractere para determinar se é um identificador ou literal e enviá-lo para a função correta para processamento. Então, isso é uma otimização de desempenho.
A outra opção seria verificar se não é um literal e deixar o domínio dos identificadores como o universo menos os literais. Mas para fazer isso, você teria que examinar todos os caracteres de cada token para saber como classificá-lo.
Há também as implicações estilísticas que os identificadores devem ser mnemônicos, de modo que as palavras são muito mais fáceis de lembrar do que números. Quando muitos idiomas originais foram escritos, definindo os estilos para as próximas décadas, eles não estavam pensando em substituir "2" por "para".
fonte
Os nomes de variáveis não podem começar com um dígito, pois podem causar alguns problemas, como abaixo:
qual é o valor de c? é 4 ou é 10!
outro exemplo:
é o primeiro 5 um número ou é um objeto (operador.) Há um problema semelhante com o segundo 5.
Talvez haja outras razões. Portanto, não devemos usar nenhum dígito no início de um nome de variável.
fonte
O uso de um dígito para iniciar o nome de uma variável torna a verificação de erros durante a compilação ou interoperação muito mais complicada.
Permitir o uso de nomes de variáveis que começaram como um número provavelmente causaria grandes problemas para os designers de idiomas. Durante a análise do código-fonte, sempre que um compilador / intérprete encontrava um token começando com um dígito em que era esperado um nome de variável, ele precisava pesquisar um conjunto enorme e complicado de regras para determinar se o token era realmente uma variável ou um erro . A complexidade adicionada ao analisador de idiomas pode não justificar esse recurso.
Desde que me lembro (cerca de 40 anos), acho que nunca usei uma linguagem que permitisse o uso de um dígito para iniciar nomes de variáveis. Tenho certeza de que isso foi feito pelo menos uma vez. Talvez alguém aqui tenha visto isso em algum lugar.
fonte
Como várias pessoas notaram, há muita bagagem histórica sobre formatos válidos para nomes de variáveis. E os designers de idiomas são sempre influenciados pelo que sabem quando criam novos idiomas.
Dito isso, quase sempre o idioma não permite que nomes de variáveis comecem com números, porque essas são as regras do design do idioma. Muitas vezes, é porque uma regra tão simples facilita muito a análise e o lexing do idioma. Nem todos os designers de idiomas sabem que esse é o motivo real. As ferramentas modernas de lexing ajudam, porque se você tentar defini-lo como permitido, elas fornecerão análises de conflitos.
OTOH, se o seu idioma tiver um caractere identificável exclusivamente para anunciar nomes de variáveis, é possível configurá-lo para que eles comecem com um número. Variações de regra semelhantes também podem ser usadas para permitir espaços nos nomes de variáveis. Mas é provável que o idioma resultante não se assemelhe muito a nenhum idioma convencional popular, se é que existe.
Para um exemplo de uma linguagem de modelagem HTML bastante simples que permite que variáveis iniciem com números e tenham espaços incorporados, consulte Qompose .
fonte
Como se você permitisse que a palavra-chave e o identificador começassem com caracteres numéricos, o lexer (parte do compilador) não conseguiria diferenciar facilmente o início de um literal numérico e de uma palavra-chave sem ficar muito mais complicado (e mais lento).
fonte
A restrição é arbitrária. Vários Lisps permitem que nomes de símbolos comecem com numerais.
fonte
COBOL permite que variáveis iniciem com um dígito.
fonte
C ++ não pode tê-lo porque os designers de linguagem fizeram disso uma regra. Se você fosse criar seu próprio idioma, certamente poderia permitir, mas provavelmente enfrentaria os mesmos problemas que eles e decidiria não permitir. Exemplos de nomes de variáveis que causariam problemas:
0x, 2d, 5555
fonte
Um dos principais problemas para relaxar convenções sintáticas é que ela introduz dissonância cognitiva no processo de codificação. Como você pensa sobre seu código pode ser profundamente influenciado pela falta de clareza que isso introduziria.
Não foi Dykstra quem disse que "o aspecto mais importante de qualquer ferramenta é o seu efeito no usuário"?
fonte
Provavelmente porque torna mais fácil para o ser humano dizer se é um número ou um identificador e por causa da tradição. Ter identificadores que pudessem começar com um dígito não complicaria muito as verificações lexicais.
Nem todos os idiomas têm identificadores proibidos começando com um dígito. Em Quarto Quarto, eles poderiam ser números, e pequenos números inteiros eram normalmente definidos como Quarto Quarto (essencialmente identificadores), pois era mais rápido ler "2" como uma rotina para inserir um 2 na pilha do que reconhecer "2" como um número. cujo valor era 2. (Ao processar a entrada do programador ou do bloco de disco, o quarto sistema dividiria a entrada de acordo com os espaços. Ele tentaria procurar o token no dicionário para ver se era uma palavra definida e se não, tentaria convertê-lo em um número e, se não, sinalizaria um erro.)
fonte
Suponha que você permita que os nomes dos símbolos comecem com números. Agora, suponha que você queira nomear uma variável 12345foobar. Como você diferenciaria isso de 12345? Na verdade, não é muito difícil fazer uma expressão regular. O problema é realmente de desempenho. Eu realmente não posso explicar por que isso está em grandes detalhes, mas basicamente se resume ao fato de que diferenciar 12345foobar de 12345 requer retroceder. Isso torna a expressão regular não determinística.
Há uma explicação muito melhor sobre isso aqui .
fonte
ifq
oudoublez
mas nãoif
oudouble
? O problema fundamental de permitir que os identificadores iniciem com dígitos seria que existem formas existentes de literais hexadecimais e números de ponto flutuante que consistem inteiramente em caracteres alfanuméricos (os idiomas usariam algo como $ 1234 ou h'1234 em vez de 0x1234 e exigiriam números como 1E23 para incluir um período, poderia evitar esse problema). Observe que as tentativas de analisar C de regex já podem ser desencadeadas por coisas como0x12E+5
.é fácil para um compilador identificar uma variável usando ASCII na localização da memória e não no número.
fonte
O compilador possui 7 fases da seguinte maneira:
O retorno é evitado na fase de análise lexical ao compilar o trecho de código. A variável como Apple, o compilador saberá seu identificador imediatamente quando encontrar o caractere da letra 'A' na fase lexical de análise. No entanto, uma variável como 123apple, o compilador não será capaz de decidir se é um número ou identificador até atingir 'a' e precisa voltar atrás na fase de análise lexical para identificar que é uma variável. Mas isso não é suportado no compilador.
Ao analisar o token, você precisa apenas olhar para o primeiro caractere para determinar se é um identificador ou literal e enviá-lo para a função correta para processamento. Então, isso é uma otimização de desempenho.
fonte
Eu acho que a resposta simples é que pode, a restrição é baseada na linguagem. No C ++ e em muitos outros, não pode, porque a linguagem não suporta. Não está embutido nas regras para permitir isso.
A pergunta é semelhante a perguntar por que o rei não pode mover quatro espaços por vez no xadrez? É porque no xadrez é uma jogada ilegal. Pode em outro jogo com certeza. Depende apenas das regras que estão sendo jogadas.
fonte
Originalmente, era simplesmente porque é mais fácil lembrar (você pode dar mais significado) nomes de variáveis como cadeias, em vez de números, embora os números possam ser incluídos na cadeia para aprimorar o significado da cadeia ou permitir o uso do mesmo nome de variável, mas designá-lo como tendo um significado ou contexto separado, mas próximo. Por exemplo, loop1, loop2 etc sempre informaria que você estava em um loop e / ou o loop 2 era um loop no loop1. Qual você prefere (tem mais significado) como uma variável: endereço ou 1121298? Qual é mais fácil de lembrar? No entanto, se o idioma usar algo para indicar que não é apenas texto ou números (como o endereço $ em $), ele realmente não deve fazer diferença, pois isso diria ao compilador que o que se segue deve ser tratado como uma variável ( nesse caso).
fonte
A variável pode ser considerada como um valor também durante o tempo de compilação pelo compilador, para que o valor possa chamar o valor novamente e novamente recursivamente
fonte
O retorno é evitado na fase de análise lexical ao compilar o trecho de código . A variável como Apple; , o compilador saberá seu identificador imediatamente quando encontrar o caractere da letra 'A' na fase de análise lexical. No entanto, uma variável como 123apple; , o compilador não poderá decidir se é um número ou identificador até que ele atinja 'a' e precise voltar atrás na fase de análise lexical para identificar se é uma variável. Mas isso não é suportado no compilador.
Referência
fonte
Não pode haver nada de errado com isso quando se declara variável. Mas há alguma ambiguidade quando tenta usar essa variável em outro lugar como este:
deixe 1 = "Olá mundo!" impressão (1) impressão (1)
print é um método genérico que aceita todos os tipos de variáveis. portanto, nessa situação, o compilador não sabe a qual (1) o programador se refere: o 1 do valor inteiro ou o 1 que armazena um valor de string. talvez seja melhor para o compilador nessa situação permitir definir algo assim, mas ao tentar usar esse material ambíguo, traga um erro com capacidade de correção para como corrigir esse erro e limpar essa ambiguidade.
fonte