it-swarm-es.com

¿Es un mal diseño para un lenguaje de programación permitir espacios en los identificadores?

Algunos lenguajes de programación ( enlace 1 , enlace 2 ) permiten espacios en sus identificadores (por ejemplo, variables, procedimientos), pero la mayoría de ellos no lo hacen y en su lugar los programadores suelen usar caso de camello , caso de serpiente y otras formas de separar palabras en nombres.

Para admitir espacios o incluso otros caracteres Unicode, algunos lenguajes de programación permiten encapsular el nombre con un determinado carácter para delimitar su inicio y fin.

¿Es una mala idea permitir espacios o simplemente no se permite por razones históricas (cuando había más limitaciones que ahora o simplemente se decidió que no valía la pena implementar)?

La pregunta es más sobre los principales pros y contras de implementarlo en lenguajes de programación recién creados.

Páginas relacionadas: enlace 1 , enlace 2 .

51
user7393973

Considera lo siguiente.

 var [Example Number] = 5;
 [Example Number] = [Example Number] + 5;
 print([Example Number]);

 int[] [Examples Array] = new int[25];
 [Examples Array][[Example Number]] = [Example Number]

Compárelo con el ejemplo más tradicional:

 var ExampleNumber = 5;
 ExampleNumber = ExampleNumber + 5;
 print(ExampleNumber);

 int[] ExamplesArray = new int[25];
 ExamplesArray[ExampleNumber] = ExampleNumber;

Estoy bastante seguro de que notó que la tensión de su cerebro para leer el segundo ejemplo fue mucho menor.

Si permite espacios en blanco en un identificador, deberá colocar algún otro elemento de lenguaje para marcar el inicio y el final de una palabra. Esos delimitadores obligan al cerebro a realizar un análisis adicional y, dependiendo de cuál elija, crear un conjunto completamente nuevo de problemas de ambigüedad para el cerebro humano.

Si no coloca delimitadores e intenta inferir de qué identificador está hablando cuando escribe código solo por contexto, invita a otro tipo de lata de gusanos:

 var Example = 5;
 var Number = 10;
 var Example Number = Example + Number;

 int[] Examples Array = new int[25];
 Examples Array[Example Number] = Example Number;

 Example Number = Example Number + Example + Number;
 print text(Example Number);

Perfectamente factible.

Un dolor total para la coincidencia de patrones de tu cerebro.

Es doloroso leer esos ejemplos no solo por la elección de las palabras que estoy eligiendo, sino también porque su cerebro toma un tiempo extra para identificar qué es cada identificador.

Considere el formato más regular, una vez más:

 var Example = 5;
 var Number = 10;
 var ExampleNumber = Example + Number;

 int[] ExamplesArray = new int[25];
 ExamplesArray[ExampleNumber] = ExampleNumber;

 ExampleNumber = ExampleNumber + Example + Number;
 printText(ExampleNumber);

¿Notas algo?

Los nombres de las variables siguen siendo terribles, pero la tensión para leerlo disminuyó. Eso sucede porque su cerebro ahora tiene un ancla natural para identificar el principio y el final de cada Palabra, lo que le permite abstraer esa parte de su pensamiento. Ya no necesita preocuparse por ese contexto: ve una interrupción en el texto, sabe que se acerca un nuevo identificador.

Al leer el código, su cerebro no lee las palabras tanto como coincide con lo que tienes en mente en este momento. Realmente no te paras a leer "ExampleWord". Ves que la forma general de la cosa, ExxxxxxWxxd, coincide con lo que hayas escondido en tu montón mental, y continúan leyendo. Es por eso que es fácil pasar por alto errores como "ExampleWord = ExapmleWord": su cerebro realmente no lo está leyendo. Solo estás combinando cosas similares.

Una vez más, considere lo siguiente:

 Example Word += Example  Word + 1;

Ahora imagínese tratando de depurar ese código. Imagine cuántas veces perderá ese espacio extra en "Palabra de ejemplo". Una carta mal colocada ya es difícil de detectar a primera vista; un espacio extra es un orden de magnitud peor.

Al final, es difícil decir que permitir espacios en blanco haría que el texto sea más legible. Me resulta difícil creer que la molestia adicional de los terminadores adicionales y la sobrecarga adicional en mi cerebro valdrían la pena usar este tipo de funcionalidad si el lenguaje con el que estoy trabajando lo tuviera.

Personalmente, lo considero un mal diseño, no por la molestia del compilador, el intérprete o lo que sea, sino porque mi cerebro tropieza en esos espacios pensando que es un nuevo identificador que está por comenzar, cuando no lo está.

En cierto sentido, nuestro cerebro sufre los mismos problemas que nuestros procesadores, cuando se trata de predicción de rama .

Así que por favor, sé amable con nuestros trenes de pensamiento. No ponga espacios en blanco en sus identificadores.

101
T. Sar

¿Es un mal diseño para un lenguaje de programación permitir espacios en los identificadores?

Respuesta corta:

Tal vez.

Respuesta ligeramente más larga:

El diseño es el proceso de identificar y ponderar soluciones conflictivas a problemas complejos, y hacer buenos compromisos que satisfagan las necesidades de las partes interesadas. No existe un "mal diseño" o "buen diseño" excepto en el contexto de los objetivos de esas partes interesadas , y usted no ha dicho cuáles son esos objetivos , entonces la pregunta es demasiado vaga para responder.

Respuesta aún más larga:

Como he mencionado anteriormente, depende de los objetivos de la circunscripción que el diseñador del lenguaje está abordando. Consideremos dos lenguajes con los que estoy familiarizado: la forma legible por humanos de MSIL, el "lenguaje intermedio" de bajo nivel con el que C # compila y C #.

C # pretende ser un lenguaje que haga que los desarrolladores de línea de negocio sean altamente productivos en entornos que Microsoft considera estratégicamente importantes. En C #, un identificador es una secuencia de uno o más caracteres UTF-16 donde todos los caracteres se clasifican como alfanuméricos o _, y el primer carácter no es un número.

Esta gramática léxica fue cuidadosamente elegida para tener características que coincidan con las necesidades de esos desarrolladores LOB estratégicamente importantes:

  • Es inequívocamente lexable como identificador; 1e10 por ejemplo, no debe ser un identificador legal porque es léxicamente ambiguo con un doble.
  • Admite modismos comúnmente utilizados en C, C++ y Java, como nombrar un campo privado _foo. C # fue diseñado para atraer a los desarrolladores que ya conocían un lenguaje LOB común.
  • Admite identificadores escritos en casi cualquier lenguaje humano. Quieres escribir var φωτογραφία = @"C:\Photos"; en C #, sigue adelante. Esto hace que el lenguaje sea más accesible para los desarrolladores que no son hablantes nativos de inglés.

Sin embargo, C # no admite espacios en los identificadores.

  • Complicaría la gramática léxica e introduciría ambigüedades que luego deben resolverse.
  • En la gran mayoría de las situaciones de interoperabilidad, no es necesario. Nadie nombra a sus miembros públicos para que tengan espacios en ellos.

Fue una buena idea no permitir caracteres distintos de letras y números en identificadores de C #.

En MSIL, por el contrario, puede nombrar una función casi cualquier cosa, incluso poner espacios u otros caracteres "extraños" en los nombres de los métodos. ¡Y de hecho, el compilador de C # se aprovecha de esto! Generará "nombres indescriptibles" para los métodos generados por el compilador que no deben ser invocados directamente por el código del usuario.

¿Por qué es una buena idea para MSIL y no para C #? Debido a que los casos de uso de MSIL son completamente diferentes:

  • MSIL no está diseñado como un lenguaje de desarrollo primario; es un lenguaje intermedio, por lo que el caso de uso principal es para desarrolladores de compiladores que intentan comprender la salida de su compilador.
  • MSIL está diseñado para poder interoperar con cualquier entorno de desarrollo de Microsoft heredado incluyendo pre.NET Visual Basic y otros OLE = Clientes de automatización, que permitieron espacios en los identificadores.
  • Como se señaló anteriormente, poder generar un nombre "indescriptible" para una función es una característica, no un error.

Entonces, ¿es una buena idea permitir espacios en los identificadores? Depende de los casos de uso del idioma. Si tienes un caso de uso sólido para permitirlo, permítelo por todos los medios. Si no lo haces, no lo hagas.

Lectura adicional: Si desea un ejemplo de un lenguaje fascinante que haga un excelente uso de identificadores complejos, consulte Inform7 , un DSL para juegos de aventura basados ​​en texto:

The Open Plain is a room. 
"A wide-open grassy expanse, from which you could really go any way at all."

Esto declara un nuevo objeto de tipo room llamado The Open Plain, y ese objeto puede ser referido como tal en todo el programa. Inform7 tiene un analizador muy rico y complejo, como se puede imaginar.

Aquí hay un ejemplo más complejo:

Before going a direction (called way) when a room (called next location) is not visited:
  let further place be the room the way from the location;
  if further place is a room, continue the action;
  change the way exit of the location to the next location;
  let reverse be the opposite of the way;
  change the reverse exit of the next location to the location.

Tenga en cuenta que way y next location y further place y reverse son identificadores en este idioma. Tenga en cuenta también que next location y the next location tienen un alias. (Ejercicio: ¿qué le está haciendo este código a la estructura de datos que mantiene el mapa de habitaciones en el juego?)

Inform7 tiene una circunscripción que quiere que el código fuente sea el idioma inglés de apariencia natural. Parecería extraño escribir este Inform7 como

  change the way exit of the location to the_next_location;

Romper la inmersión al hacerlo. Contraste esto con la respuesta (excelente) de T. Sar que hace el punto de contraste: que los desarrolladores en lenguajes LOB rompen la inmersión para tratar de analizar mentalmente dónde están los identificadores. De nuevo, se reduce a contexto y objetivos.

59
Eric Lippert

Uno relativamente conocido ejemplo es de algún código Fortran en el que un solo error tipográfico cambió por completo el significado del código.

Estaba destinado a repetir una sección de código 100 veces (con I como contador de bucle):

DO 10 I = 1,100

Sin embargo, la coma fue mal escrita como un punto:

DO 10 I = 1.100

Debido a que Fortran permite espacios en los identificadores (y porque crea automáticamente variables si no han sido declaradas), la segunda línea es perfectamente válida: crea implícitamente una variable real espuria llamada DO10I, y le asigna el número 1.1. Entonces el programa compiló bien sin errores; simplemente no pudo ejecutar el bucle.

El código en cuestión controlaba un cohete; Como puedes imaginar, ese tipo de error podría haber sido catastrófico. Afortunadamente, en este caso, el error se detectó en las pruebas y ninguna nave espacial resultó dañada.

Creo que esto muestra bastante bien uno de los peligros de permitir espacios en los identificadores ...

15
gidds

¿Es un mal diseño para un lenguaje de programación permitir espacios en los identificadores?

Olvidó detalles importantes de implementación:

¿Qué es código fuente para usted?

Me gusta la definición de FSF : la forma preferida en la que trabajan los desarrolladores. Es una definición social, no técnica.

En algunos idiomas y su implementación en la década de 1980 (piense en las máquinas originales Smalltalk y 1980 Smalltalk), el código fuente no era una secuencia de caracteres. Era un árbol de sintaxis abstracta y fue manipulado por el usuario, con el mouse y el teclado, usando alguna GUI.

En cierto sentido, LISP común acepta espacios en sus símbolos.

Podrías decidir (que es un lote de trabajo) codiseñar tanto tu lenguaje de programación ( documentado en algún informe dando ambos sintaxis y semántica ), su implementación (como algún software) y su editor o IDE ( como algún software).

Lea las discusiones anteriores en tunes.org . Lea el antiguo trabajo de INRIA en

@TechReport{Jacobs:1992:Centaur,
 author =       {Jacobs, Ian and Rideau-Gallot, Laurence},
 title =        {a {\textsc{Centaur}} Tutorial},
 institution =  {\textsc{Inria} Sophia-Antipolis},
 year =         1992,
 number =       {RT-140},
 month =        {july},
 url =          {ftp://www.inria.fr/pub/rapports/RT-140.ps}
}

y

@techreport{donzeaugouge:inria-mentor,
 TITLE =        {{Programming environments based on structured
                 editors : the \textsc{Mentor} experience}},
 AUTHOR =       {Donzeau-Gouge, Véronique and Huet, Gérard and Lang,
                 Bernard and Kahn, Gilles},
 URL =          {https://hal.inria.fr/inria-00076535},
 TYPE =         {Research Report},
 NUMBER =       {RR-0026},
 INSTITUTION =  {{INRIA}},
 YEAR =         1980,
 PDF =
              {https://hal.inria.fr/inria-00076535/file/RR-0026.pdf},
 HAL_ID =       {inria-00076535},
 HAL_VERSION =  {v1},
}

Vea también mi informe borrador de Bismon y http://refpersys.org/

Mi sueño RefPerSys es codiseñar un lenguaje de programación tan declarativo con un Nice IDE para ello. Sé que podría llevar una década. Siéntase libre de pensar que estamos locos, en algún sentido ¡estamos!

Desde el punto de vista de la usabilidad, coloreado de sintaxis y autocompletado es más importante que los espacios en los identificadores (mire ambos GtkSourceView y CodeMirror para inspiración). Visualmente un guión bajo _ se ve cerca de un carácter de espacio. Y si codifica su propio IDE, puede aceptar ctrlspace como entrada para "espacios dentro de nombres". Mi opinión es que ℕ y ∀ deberían ser "palabras clave", la pregunta es cómo se escriben. Estoy soñando con escribir (inspirado en LaTeX) \forallESC para obtener un ∀ (y escuché de algunos emacs submodo para eso).

NB: Odio Python (y Makefile - s) porque los espacios en blanco (o pestañas) son significativos allí.

8

No es un diseño intrínsecamente malo ¡permitir espacios en los nombres de los símbolos. Esto se puede mostrar con un simple contraejemplo.

Kotlin permite espacios en los nombres. También tiene convenciones de codificación oficiales que establecen cuando está bien usar esta función :

Nombres para métodos de prueba

En las pruebas (y solo en las pruebas), es aceptable usar nombres de métodos con espacios encerrados entre comillas.

Ejemplo:

class MyTestCase {
     @Test fun `ensure everything works`() { /*...*/ }

"Bueno" y "malo" es, por supuesto, subjetivo, pero el uso de espacios en los nombres de los métodos de prueba hace que el código de la prueba sea mucho más agradable de leer, y también los resultados de las pruebas. una descripción de prueba legible por humanos por separado.

El punto importante aquí es que estos métodos normalmente no se llamarán explícitamente a partir del código escrito por humanos, por lo que solo el lugar donde aparece el nombre está en la definición del método. Creo que esta es una distinción importante para considerar cuándo los espacios pueden ser una buena idea en los nombres de los símbolos: solo cuando el símbolo lo escribe una sola vez el programador.

6
hyde

Regla de oro:

Los errores son proporcionales al tiempo que lleva leer el código en voz alta.

Cualquier cosa que aumente el número de paréntesis abierto, paréntesis cerrado, paréntesis rizado abierto, paréntesis rizado cerrado, paréntesis abierto, paréntesis cerrado ... aumentará el número de errores en el código.

Esta es una de las razones por las que * es una estrella o un splat, y no un asterisco. # es shhh,! es explosión Los matemáticos sospecho que también tienen expresiones verbales cortas para sus símbolos, estoy seguro.

Es por eso que los campos tecnológicos se llenan de siglas y abreviaturas: pensamos en palabras. Tenemos una capacidad de atención finita y solo podemos contener tantos símbolos en nuestra cabeza. Entonces agrupamos y agrupamos las cosas.

ReallyReallyLongIdentifier puede hacer lo mismo. Allí la compensación es entre recordar para qué sirve y enredarse en nuestros procesos de pensamiento. Pero ReallyReallyLongIndentifer es aún mejor que QzslkjfZslk19

Cuanto más lejos de su creación se usa, más necesita ser memorable. Por lo tanto, i, j, k se usan para construcciones de bucles, como las moscas de mayo que viven durante la vida de un bucle, y ese bucle comienza y termina en la misma pantalla.

Esto se extiende a la codificación también:

A = FunctionAlpha (21, $ C, $ Q)

B = FunctionBeta ($ A, $ D, $ R)

es más limpio que

B = FunctionBeta (FunctionAlpha (21, $ C, $ Q), $ D, $ R)

Creo que esta es una de las razones por las cuales las hojas de cálculo tienen tasas de error tan abismales, codificación incorrecta: excepto al agregar celdas/filas/columnas temporales, no hay forma de evitar declaraciones anidadas desordenadas.

3
Sherwood Botsford

Me tomó MUCHO tiempo comprender realmente que nunca habrá un mejor idioma. Para un equipo de programación, los aspectos más importantes son que el lenguaje sea bien conocido, con el apoyo de muchas herramientas, debe tener una sintaxis de lenguaje mínima y debe sorprenderle lo menos posible.

Para un solo codificador, un lenguaje poderoso que permite ciclos rápidos de prueba/ejecución es excelente.

Para un administrador, un idioma adaptado al lenguaje Shell del sistema operativo es crítico.

Para algunos idiomas de trabajo compartidos entre disciplinas, los DSL pueden ser buenos.

¿Hay un lugar para un idioma con espacios, probablemente? Viola las reglas no sorprendentes, pero encaja muy bien con los objetivos de DSL.

Sin embargo, una cosa que no creo que nadie haya mencionado, con un personalizado IDE, en realidad podría tener un espacio duro y un espacio blando. Se verían similares (tal vez tengan diferentes tonos en el IDE) .

Para el caso, puede hacerlo ahora con cualquier idioma, simplemente active su IDE para que los guiones bajos se muestren como espacios. Cualquiera que cree complementos de Eclipse probablemente podría hacerlo en una hora .

También es posible convertir pragmáticamente el caso de camello a "palabras con espacios", su IDE podría hacer eso por usted, pero sería un poco más extraño.

0
Bill K