¿Por qué los nombres de variables no pueden comenzar con números?

Estuve trabajando con un nuevo desarrollador de C ++ hace un tiempo cuando me hizo la pregunta: “¿Por qué los nombres de variables no pueden comenzar con números?”

No pude encontrar una respuesta, excepto que algunos números pueden contener texto (123456L, 123456U) y eso no sería posible si los comstackdores pensaran que todo con una cierta cantidad de caracteres alfabéticos tiene un nombre de variable.

¿Esa era la respuesta correcta? ¿Hay más razones?

string 2BeOrNot2Be = "that is the question"; // Why won't this compile? 

Porque entonces una cadena de dígitos sería un identificador válido, así como un número válido.

 int 17 = 497; int 42 = 6 * 9; String 1111 = "Totally text"; 

Bueno, piensa en esto:

 int 2d = 42; double a = 2d; 

¿Qué es? 2.0? o 42?

Sugerencia, si no lo obtiene, d después de un número significa el número antes de que sea un doble literal

Es una convención ahora, pero comenzó como un requisito técnico.

En el pasado, los analizadores de lenguajes como FORTRAN o BASIC no requerían el uso de espacios. Entonces, básicamente, los siguientes son idénticos:

 10 V1=100 20 PRINT V1 

y

 10V1=100 20PRINTV1 

Ahora supongamos que se permitieron los prefijos numéricos. ¿Cómo interpretarías esto?

 101V=100 

como

 10 1V = 100 

o como

 101 V = 100 

o como

 1 01V = 100 

Entonces, esto fue hecho ilegal.

Porque se evita el rastreo en el análisis léxico durante la comstackción. Una variable como:

 Apple; 

el comstackdor sabrá que es un identificador de inmediato cuando cumpla con la letra ‘A’.

Sin embargo, una variable como:

 123apple; 

el comstackdor no podrá decidir si se trata de un número o identificador hasta que llegue a ‘a’, y como resultado, necesita retroceder.

Los comstackdores / analizadores sintácticos / analizadores léxicos fueron hace mucho, mucho tiempo, pero creo que recuerdo haber dificultades para determinar inequívocamente si un carácter numérico en la unidad de comstackción representaba un literal o un identificador.

Los idiomas donde el espacio es insignificante (como ALGOL y la FORTRAN original, si mal no recuerdo) no pudieron aceptar números para comenzar los identificadores por ese motivo.

Esto se remonta a mucho antes de las notaciones especiales para denotar el almacenamiento o la base numérica.

Es probable que una decisión se deba a varias razones, cuando analiza el token solo tiene que mirar al primer caracter para determinar si es un identificador o literal y luego enviarlo a la función correcta para su procesamiento. Entonces esa es una optimización del rendimiento.

La otra opción sería verificar si no es un literal y dejar el dominio de los identificadores como el universo menos los literales. Pero para hacer esto tendrías que examinar cada personaje de cada token para saber cómo clasificarlo.

También se supone que los identificadores de implicaciones estilísticas son mnemónicos, por lo que las palabras son mucho más fáciles de recordar que los números. Cuando se escribieron muchos de los idiomas originales configurando los estilos para las próximas décadas, no estaban pensando en sustituir “2” por “hasta”.

Estoy de acuerdo en que sería útil permitir que los identificadores comiencen con un dígito. Una o dos personas han mencionado que puede evitar esta restricción anteponiendo un guión bajo a su identificador, pero eso es realmente desagradable.

Creo que parte del problema proviene de literales numéricos como 0xdeadbeef, lo que dificulta crear reglas fáciles de recordar para los identificadores que pueden comenzar con un dígito. Una forma de hacerlo sería permitir que cualquier cosa que coincida con [A-Za-z _] + NO sea una palabra clave o número literal. El problema es que daría lugar a cosas raras como 0xdeadpork, pero no a 0xdeadbeef. En definitiva, creo que deberíamos ser justos con todas las carnes: P.

Cuando estaba aprendiendo C por primera vez, recuerdo que las reglas para los nombres variables eran arbitrarias y restrictivas. Lo peor de todo era que eran difíciles de recordar, así que dejé de intentar aprenderlos. Simplemente hice lo que parecía correcto, y funcionó bastante bien. Ahora que he aprendido mucho más, no parece tan malo, y finalmente llegué a aprender bien.

El uso de un dígito para comenzar un nombre de variable hace que la comprobación de errores durante la comstackción o la interacción sea mucho más complicada.

Permitir el uso de nombres de variables que comenzaron como un número probablemente causaría grandes problemas para los diseñadores de idiomas. Durante el análisis del código fuente, cada vez que un comstackdor / intérprete encontraba un token que comenzaba con un dígito donde se esperaba un nombre de variable, tenía que buscar a través de un enorme y complicado conjunto de reglas para determinar si el token era realmente una variable o un error . La complejidad añadida añadida al analizador de lenguaje puede no justificar esta característica.

Desde que tengo memoria (alrededor de 40 años), no creo haber usado nunca un lenguaje que permitiera el uso de un dígito para comenzar los nombres de las variables. Estoy seguro de que esto se hizo al menos una vez. Tal vez, alguien aquí realmente ha visto esto en alguna parte.

Como varias personas han notado, hay un montón de equipaje histórico sobre formatos válidos para nombres variables. Y los diseñadores de idiomas siempre están influenciados por lo que saben cuando crean nuevos lenguajes.

Dicho esto, prácticamente todo el tiempo un lenguaje no permite que los nombres de variables comiencen con números porque esas son las reglas del diseño del lenguaje. A menudo es porque una regla tan simple hace que el análisis sintáctico y el lexing del lenguaje sean mucho más fáciles. Sin embargo, no todos los diseñadores de idiomas saben que esta es la verdadera razón. Las herramientas modernas de lexing ayudan, porque si intentas definirlas como permisibles, te darán conflictos de análisis.

OTOH, si su idioma tiene un carácter de identificación única para anunciar nombres de variables, es posible configurarlo para que comience con un número. Variaciones de reglas similares también se pueden usar para permitir espacios en nombres de variables. Pero es probable que el lenguaje resultante no se parezca mucho a ningún lenguaje convencional popular, en todo caso.

Para obtener un ejemplo de un lenguaje de plantillas HTML bastante simple que permite que las variables comiencen con números y tengan espacios incrustados, consulte Qompose .

Porque si permitía que la palabra clave y el identificador comenzaran con caracteres numéricos, el lexer (parte del comstackdor) no podía diferenciar fácilmente entre el comienzo de un literal numérico y una palabra clave sin complicarse demasiado (y más lentamente).

La restricción es arbitraria. Varios Lisps permiten que los nombres de símbolos comiencen con números.

Los nombres de las variables no pueden comenzar con un dígito, porque pueden causar algunos problemas como los siguientes:

 int a = 2; int 2 = 5; int c = 2 * a; 

¿Cuál es el valor de c? es 4, o es 10!

otro ejemplo:

 float 5 = 25; float b = 5.5; 

es el primer 5 un número, o es un objeto (operador). Hay un problema similar con el segundo 5.

Tal vez, hay algunas otras razones. Por lo tanto, no deberíamos usar ningún dígito en el comienzo de un nombre de variable.

COBOL permite que las variables comiencen con un dígito.

C ++ no puede tenerlo porque los diseñadores del lenguaje lo convirtieron en una regla. Si tuviera que crear su propio idioma, sin duda podría permitirlo, pero probablemente se encuentre con los mismos problemas que ellos y decida no permitirlo. Ejemplos de nombres de variables que causarían problemas:

0x, 2d, 5555

Uno de los problemas clave para relajar las convenciones sintácticas es que introduce una disonancia cognitiva en el proceso de encoding. Cómo piensas acerca de tu código podría estar profundamente influenciado por la falta de claridad que esto introduciría.

¿No fue Dykstra quien dijo que el “aspecto más importante de cualquier herramienta es su efecto en su usuario”?

Probablemente porque hace que sea más fácil para el ser humano saber si se trata de un número o un identificador, y debido a la tradición. Tener identificadores que podrían comenzar con un dígito no complicaría mucho los escaneos léxicos.

No todos los idiomas tienen identificadores prohibidos que comiencen con un dígito. En adelante, podrían ser números, y los enteros pequeños normalmente se definían como palabras anteriores (esencialmente identificadores), ya que era más rápido leer “2” como rutina para insertar un 2 en la stack que reconocer “2” como un número cuyo valor era 2. (Al procesar la entrada del progtwigdor o del bloque de disco, el sistema Forth dividiría la entrada según los espacios. Intentaría buscar el token en el diccionario para ver si era una palabra definida, y si no, intentaría traducirlo a un número, y si no marcaría un error.)

Supongamos que permite que los nombres de símbolos comiencen con números. Ahora supongamos que quiere nombrar una variable 12345foobar. ¿Cómo diferenciaría esto de 12345? En realidad, no es terriblemente difícil de hacer con una expresión regular. El problema es realmente uno de rendimiento. Realmente no puedo explicar por qué esto es en gran detalle, pero básicamente se reduce al hecho de que para diferenciar 12345foobar de 12345 es necesario retroceder. Esto hace que la expresión regular no sea determinista.

Hay una explicación mucho mejor de esto aquí .

es fácil para un comstackdor identificar una variable usando ASCII en la ubicación de la memoria en lugar del número.

Creo que la respuesta simple es que sí, la restricción está basada en el lenguaje. En C ++ y muchos otros no puede porque el lenguaje no lo admite. No está incorporado en las reglas para permitir eso.

La pregunta es similar a preguntar por qué el Rey no puede mover cuatro espacios a la vez en el Ajedrez. Es porque en el Ajedrez es un movimiento ilegal. Puede en otro juego seguro. Solo depende de las reglas que está jugando.

Originalmente era simplemente porque es más fácil recordar (puede darle más sentido) nombres de variables como cadenas en lugar de números, aunque se pueden incluir números dentro de la cadena para mejorar el significado de la cadena o permitir el uso del mismo nombre de variable, pero tenerlo designado como teniendo un significado o contexto separado pero cerrado. Por ejemplo, loop1, loop2, etc. siempre te dejarían saber que estabas en un bucle y / o que el bucle 2 era un bucle dentro de loop1. ¿Cuál preferiría (tiene más significado) como variable: dirección o 1121298? ¿Cuál es más fácil de recordar? Sin embargo, si el lenguaje utiliza algo para indicar que no solo texto o números (como la dirección $ in $) realmente no debería marcar la diferencia, ya que eso le diría al comstackdor que lo que sigue debe ser tratado como una variable ( en este caso). En cualquier caso, se trata de lo que los diseñadores de idiomas quieren usar como reglas para su lenguaje.

La variable también puede ser considerada como un valor durante el tiempo de comstackción por el comstackdor, por lo que el valor puede llamar el valor una y otra vez de forma recursiva.

Se evita el retroceso en la fase de análisis léxico mientras se comstack el fragmento de código . La variable como Apple; , el comstackdor sabrá que es un identificador de inmediato cuando se encuentre con el carácter de la letra ‘A’ en la fase de análisis léxico. Sin embargo, una variable como 123apple; , el comstackdor no podrá decidir si es un número o identificador hasta que llegue a ‘a’ y necesite retroceder para entrar en la fase de análisis léxico para identificar que es una variable. Pero no es compatible en el comstackdor.

Referencia

El comstackdor tiene 7 fases de la siguiente manera:

  1. Análisis léxico
  2. Análisis de syntax
  3. Análisis semántico
  4. Generación de código intermedio
  5. Optimización de código
  6. Codigo de GENERACION
  7. Tabla de símbolos

Se evita el retroceso en la fase de análisis léxico mientras se comstack el fragmento de código. La variable como Apple, el comstackdor sabrá que es un identificador de inmediato cuando se encuentra con el carácter de la letra ‘A’ en la fase de análisis léxico. Sin embargo, una variable como 123apple, el comstackdor no podrá decidir si es un número o identificador hasta que llegue a ‘a’ y necesite retroceder para entrar en la fase de análisis léxico para identificar que es una variable. Pero no es compatible en el comstackdor.

Cuando está analizando el token, solo tiene que mirar el primer caracter para determinar si es un identificador o literal y luego enviarlo a la función correcta para su procesamiento. Entonces esa es una optimización del rendimiento.

No puede haber nada de malo cuando se trata de declarar la variable. Pero hay cierta ambigüedad cuando intenta usar esa variable en otro lugar como este:

let 1 = “¡Hola mundo!” imprimir (1) imprimir (1)

print es un método genérico que acepta todos los tipos de variable. entonces en esa situación el comstackdor no sabe a qué (1) el progtwigdor se refiere: el 1 del valor entero o el 1 que almacena un valor de cadena. Tal vez sea mejor para el comstackdor en esta situación que permita definir algo así, pero al tratar de usar estas cosas ambiguas, traiga un error con la capacidad de corrección de cómo solucionar el error y eliminar esta ambigüedad.