A maioria das linguagens de programação parece ter sido projetada para não permitir que se declare um identificador que começa com um número. Eu só estava curioso para saber o motivo. Já pesquisei na web, mas não consegui encontrar uma explicação satisfatória.
32
Respostas:
Em C / C ++, um número seguido por uma letra é considerado uma constante numérica e a sequência a seguir qualifica o tipo da constante. Então, por exemplo (estes são VC ++, não tenho certeza de como são padrão):
Portanto, a) é mais fácil para o lexer, como Daniel disse, mas também b) faz uma distinção explícita, pois 0y pode ser uma variável, mas 0u nunca seria. Além disso, outros qualificadores, como "i64", foram adicionados muito mais tarde que "l" ou "u" e desejam manter a opção de adicionar mais, se necessário.
fonte
A conveniência das pessoas que implementam o lexer. (Não, sério, é isso. Várias línguas têm outros motivos, mas, no final, tudo se resume a isso.)
fonte
0flu
fosse um literal e0glu
um identificador local.int 0u = 5; unsigned int x = 0u;
No entanto, você escolhe definir a interpretação desse código (provavelmente x == 0 ou x == 5), as pessoas ficarão confusas por causa da ambiguidade. Mesmo que fosse trivial implementar o compilador dessa maneira, um bom designer provavelmente não o faria.Considere os 2 casos a seguir:
Caso 1
Vamos supor que um identificador possa começar com um número.
Portanto, uma declaração como a seguir seria válida (já que um identificador pode ter 1 ou mais caracteres):
Quando tento usar a variável acima em um programa, isso resulta em ambiguidade do compilador:
Na declaração,
a=3
qual é o papel de 3 (é uma variável com valor 5 ou é o número 3)?Caso 2
Ao contrário do exemplo acima, vamos supor que um idioma realmente permita identificadores iniciando com um número, enquanto não permite que numerais sejam usados como identificadores. Isso pode causar os seguintes problemas:
As regras de linguagem relativas à variável que diz que uma variável pode consistir em 1 ou mais caracteres terão que ser redefinidas para uma regra complexa como: Uma variável pode ter um ou mais caracteres e deve ser única se não começar com um número enquanto não pode ter comprimento de caractere único ao iniciar com um número (etc.)
O compilador precisará verificar e relatar casos de erro quando todos os números (por exemplo, 333) e sufixos de alfabeto válidos (por exemplo, 34L) estiverem sendo usados como nomes de variáveis. Em linguagens de tipos vagos, como Python e JS, nas quais você pode usar variáveis em tempo real sem declará-las, pode até ser impossível verificar os casos especiais que envolvem todos os números, por exemplo:
if (33==5)
Aqui, 33 pode ser uma variável não declarada errônea que o usuário declarou. Mas o compilador não poderá identificar isso e relatar o erro.Fazer essa restrição impedirá que o programador use números como nomes de identificador.
fonte
int char = float
seria desastroso ?int
é uma palavra-chave e não um identificador? Bem,int
tem maior precedência, assim como lexemes numéricos.int 3,a; 3=5; a=3;
Na instrução a = 3, 3 é interpretado como um identificador ou como um número? Isso causa ambiguidade. Espero que esteja claro.Na maioria das vezes, isso não tem nada a ver com facilitar para os escritores do compilador e analisar a eficiência, mas mais com o design de uma sintaxe que incentive códigos legíveis e inequívocos.
Os designers da linguagem pensaram que seria bom poder escrever literais numéricos como o número 1 como apenas 1 .
Seria perfeitamente possível projetar uma sintaxe de linguagem onde literais numéricos fossem citados de alguma forma, por exemplo, tildas, de modo que o literal numérico do número um fosse codificado como ~ 1 ~ e qualquer coisa que não fosse uma palavra-chave e não estivesse entre aspas seria tratada como um nome de variável .
Então você pode codificar instruções como:
Mas também:
Seja qual for a sintaxe escolhida, o código ambíguo e difícil de seguir é inevitável.
A linguagem C e a maioria das linguagens de "colchetes" descendentes de C também consideraram uma boa idéia permitir que os programadores codificassem diretamente os literais Octal e Hexadecimal e especificar o tipo de literal, se isso fosse importante. tão
Portanto, mesmo que você permita que nomes de variáveis iniciem com um número seguido por uma combinação de números e letras que incluam pelo menos uma letra, você apresentaria ao programador o problema de decidir se um determinado grupo formou um nome de variável ou um literal numérico, de modo que
Essa ambiguidade não ajudaria ninguém a escrever ou ler um programa.
Para um exemplo do mundo real estreitamente relacionado, você pode olhar para a linguagem PL / 1, cujos designers pensaram que poder usar palavras-chave como nomes de variáveis era uma boa idéia para que:
É um código válido que compila e executa.
fonte
O Fortran teve um enorme efeito sobre como os idiomas posteriores foram projetados. Desde o início (alguns desses problemas foram corrigidos), o Fortran quase não tinha regras que restringissem o nome que você poderia dar a um identificador. Isso tornou a linguagem extremamente difícil de analisar tanto para compiladores quanto para programadores. Aqui está um exemplo clássico:
Aqui marquei as "palavras-chave do idioma" com K e os identificadores (nomes de variáveis) I. Dado que não há diferença na ortografia, acho que você provavelmente pode entender como isso pode ser confuso. Obviamente, este é um exemplo extremo e é improvável que alguém tenha escrito um código como esse de propósito. Às vezes as pessoas fizeram "reciclar" palavras-chave linguagem como nomes de identificadores embora - e em muitos casos, um erro de digitação simples podem resultar em código que a especificação linguagem disse deve ser analisado desta forma, mesmo que não se destinava a todos. Para outro exemplo conhecido, compare isso:
para isso:
O primeiro é um loop do - iterando um bloco de código 10 vezes. O segundo, no entanto, teve a vírgula alterada para um ponto decimal; portanto, está atribuindo o valor
1.10
a uma variável chamadado 10 i
.Isso também significava que escrever um analisador Fortran era relativamente difícil - você não podia ter certeza de que o
do
início da linha era realmente uma palavra-chave até chegar ao final da linha e verificar se todos os outros elementos de umdo
loop estavam presentes. O analisador geralmente tinha que estar pronto para "voltar atrás", analisando novamente a linha desde o início para chegar à resposta "correta" (mas muitas vezes não intencional) do que realmente estava lá.Depois de alguns anos disso, os designers de idiomas (a maioria deles de qualquer maneira) foram para o extremo oposto - restringindo quase tudo sobre o idioma o máximo possível, sem que os usuários se queixassem demais .
No início, o BASIC, por exemplo, basicamente dizia que você não podia usar uma palavra-chave como parte de um identificador - por exemplo,
fora=1
seria analisado comofor a = 1
(isto é, o início de umfor
loop, não uma atribuição). Aparentemente, isso gerou reclamações suficientes e não durou muito. A regra sobre iniciar um identificador com um dígito aparentemente não gerou muitas reclamações, portanto continua sendo usada (pelo menos na maioria dos idiomas).fonte
É provável que essa convenção tenha evoluído de decisões muito precoces de design de linguagem histórica, pois nas primeiras máquinas o compilador inteiro, incluindo análise lexical, precisou rodar em alguns kWords, menos memória do que apenas o cache de dados do processador de primeiro nível nos dispositivos móveis atuais, portanto, os nomes de variáveis permitidos eram muito limitados e precisavam ser fáceis de distinguir das constantes numéricas em muito poucos códigos op.
Assim, a convenção se tornou a que gerações de programadores estão acostumados.
fonte
Não é uma regra necessária para a linguagem de programação, mas apenas a convenção usada por muitos designers de linguagem.
Posso projetar uma linguagem radicalmente diferente que permita todos os caracteres para identificadores. Para todas as linhas de código, o primeiro caractere de 20 caracteres descreverá o tipo de instrução, o próximo caractere de 20 definirá o primeiro símbolo da instrução e o próximo caractere de 20 caracteres será operando para a instrução. Este idioma será executado em um processador de pilha.
Este código pode ser traduzido em C, como abaixo:
Isso é tudo. Não faz sentido, e a regra do número sem identificadores também não faz sentido em termos lógicos.
fonte
Além de "conveniência para o lexer", acho que também vale a pena considerar "conveniência para o leitor".
Ao ler o código, você precisa identificar rápida e repetidamente quais palavras são identificadores e quais são números. Procurar um dígito no início é mais fácil em nossa correspondência visual de padrões; seria uma tarefa se tivéssemos que verificar cuidadosamente todos os personagens para ter certeza.
fonte
A resposta a esta pergunta está no autômato ou no autômato finito, que define a expressão regular. A regra é ... os compiladores precisam de algoritmos ou regras exatas para decidir a cada caractere que analisam. Se fosse permitido aos identificadores começar com um número, o compilador estará em uma correção .. sobre a natureza do token que vem ... será um número ou um identificador ... e como os compiladores não podem voltar às posições anteriores .. .para deixar claro para o compilador que o token que vem é precisamente um identificador ou um número ... essa restrição existe ... porque isso ... o compilador sabe apenas verificando o primeiro caractere que o token que vem é um identificador ou um número.
fonte