Tal vez no soy de este planeta, pero me parece que lo siguiente debería ser un error de sintaxis:
int a[] = {1,2,}; //extra comma in the end
Pero no lo es. Me sorprendió cuando este código se compiló en Visual Studio, pero aprendí a no confiar en el compilador MSVC en lo que respecta a las reglas de C ++, por lo que verifiqué el estándar y también está permitido por el estándar. Puedes ver 8.5.1 para las reglas gramaticales si no me crees.
¿Por qué está permitido esto? Esta puede ser una pregunta estúpida e inútil, pero quiero que entiendas por qué te pregunto. Si se tratara de un caso secundario de una regla gramatical general, lo entendería: decidieron no hacer que la gramática general sea más difícil simplemente para no permitir una coma redundante al final de una lista de inicializadores. Pero no, la coma adicional está explícitamente permitida. Por ejemplo, no está permitido tener una coma redundante al final de una lista de argumentos de llamada a función (cuando la función toma ...
), lo cual es normal .
Entonces, de nuevo, ¿hay alguna razón particular por la cual esta coma redundante esté explícitamente permitida?
fuente
;
cuando está claro que el próximo token es en realidad una siguiente declaración?for()
por ejemplo), al agregarlo, se genera una advertencia del compilador.if (x = 1)
no es ambiguo en la gramática, pero es muy ambiguo para los humanos, y por lo tanto arroja una advertencia.if
ejemplo tampoco es ambiguo. ¡No creo que "ambiguo" signifique lo que crees que significa!Respuestas:
Facilita la generación de código fuente y también la escritura de código que puede ampliarse fácilmente en una fecha posterior. Considere qué se requiere para agregar una entrada adicional a:
... debe agregar la coma a la línea existente y agregar una nueva línea. Compare eso con el caso donde los tres ya tienen una coma después, donde solo tiene que agregar una línea. Del mismo modo, si desea eliminar una línea, puede hacerlo sin preocuparse de si es la última línea o no, y puede reordenar las líneas sin jugar con comas. Básicamente significa que hay una uniformidad en la forma en que tratas las líneas.
Ahora piense en generar código. Algo como (pseudocódigo):
No debe preocuparse si el elemento actual que está escribiendo es el primero o el último. Mucho mas simple.
fuente
Es útil si haces algo como esto:
fuente
var a = [1, 2,];
también la mayoría de los otros lenguajes que conozco ... ActionScript, Python, PHP.undefined
.Facilidad de uso para el desarrollador, creo.
Además, si por alguna razón tuvo una herramienta que generó código para usted; la herramienta no tiene que preocuparse por si es el último elemento en la inicialización o no.
fuente
Siempre he asumido que hace que sea más fácil agregar elementos adicionales:
simplemente se convierte en:
en una fecha posterior.
fuente
[1,2,3,]
está bien, pero{a:1, b:2, c:3,}
no lo está).Todo lo que todos dicen sobre la facilidad de agregar / eliminar / generar líneas es correcto, pero el verdadero lugar en el que brilla esta sintaxis es cuando se combinan los archivos de origen. Imagina que tienes esta matriz:
Y suponga que ha verificado este código en un repositorio.
Luego, tu amigo lo edita y agrega al final:
Y simultáneamente lo editas, agregando al principio:
Semánticamente, este tipo de operaciones (agregar al principio, agregar al final) debe ser completamente seguro y su software de versiones (con suerte git) debería ser capaz de automatizar. Lamentablemente, este no es el caso porque su versión no tiene coma después del 9 y la de su amigo sí. Mientras que, si la versión original tuviera el 9 final, se habrían automatizado.
Entonces, mi regla general es: use la coma final si la lista abarca varias líneas, no la use si la lista está en una sola línea.
fuente
La coma final, creo, está permitida por razones de compatibilidad con versiones anteriores. Hay una gran cantidad de código existente, principalmente generado automáticamente, que pone una coma final. Hace que sea más fácil escribir un bucle sin condiciones especiales al final. p.ej
Realmente no hay ninguna ventaja para el programador.
PD: Aunque es más fácil generar automáticamente el código de esta manera, en realidad siempre me ocupé de no poner la coma final, los esfuerzos son mínimos, se mejora la legibilidad y eso es más importante. Escribe el código una vez, lo lee muchas veces.
fuente
int a = b + c +;
oif(a && b &&);
será más fácil copiar y pegar cualquier cosa al final y más fácil escribir generadores de código. Este problema es trivial y subjetivo, en tales casos siempre es bueno hacer lo mejor para el lector de código.&&
operador, a veces hago condicionales comoif (true \n && b1 \n && b2)
para poder agregar y eliminar líneas según sea necesario.Una de las razones por las que esto está permitido hasta donde yo sé es que debería ser simple generar código automáticamente; no necesita ningún manejo especial para el último elemento.
fuente
Hace que los generadores de código que escupen matrices o enumeraciones sean más fáciles.
Imagina:
Es decir, no es necesario hacer un manejo especial del primer o último elemento para evitar escupir la coma final.
Si el generador de código está escrito en Python, por ejemplo, es fácil evitar escupir la coma final utilizando la
str.join()
función:fuente
Me sorprende que, después de todo este tiempo, nadie haya citado el Manual de referencia anotado de C ++ ( ARM ), que dice lo siguiente sobre [dcl.init] con énfasis en el mío:
aunque la gramática ha evolucionado desde que se escribió ARM, el origen permanece.
y podemos ir a la justificación de C99 para ver por qué esto se permitió en C y dice:
fuente
Veo un caso de uso que no se mencionó en otras respuestas, nuestras Macros favoritas:
Agregar macros para manejar el último
,
sería un gran dolor. Con este pequeño cambio en la sintaxis, esto es trivial de administrar. Y esto es más importante que el código generado por la máquina porque generalmente es mucho más fácil hacerlo en una lengua completa de Turing que un preprocesador muy limitado.fuente
El único lenguaje donde, en la práctica *, no está permitido es Javascript, y causa una cantidad innumerable de problemas. Por ejemplo, si copia y pega una línea desde el centro de la matriz, péguela al final y olvidó eliminar la coma, entonces su sitio estará totalmente roto para sus visitantes de IE.
* En teoría está permitido, pero Internet Explorer no sigue el estándar y lo trata como un error
fuente
var x = [,,,]
es legal (excepto en IE <9, pero la especificación dice que es legal)Es más fácil para las máquinas, es decir, el análisis y la generación de código. También es más fácil para los humanos, es decir, modificación, comentarios y elegancia visual a través de la coherencia.
Suponiendo C, ¿escribirías lo siguiente?
No. No solo porque la declaración final es un error, sino también porque es inconsistente. Entonces, ¿por qué hacer lo mismo con las colecciones? Incluso en los idiomas que le permiten omitir los últimos puntos y comas y comas, a la comunidad generalmente no le gusta. A la comunidad de Perl, por ejemplo, no parece gustarle omitir punto y coma, excluir frases. Aplican eso a las comas también.
No omita comas en colecciones multilínea por la misma razón por la que no omite puntos y comas para bloques de código multilínea. Quiero decir, no lo harías incluso si el idioma lo permitiera, ¿verdad? ¿Correcto?
fuente
La razón es trivial: facilidad para agregar / eliminar líneas.
Imagine el siguiente código:
Ahora, puede agregar / eliminar elementos fácilmente a la lista sin tener que agregar / eliminar la coma final a veces.
A diferencia de otras respuestas, realmente no creo que la facilidad de generar la lista sea una razón válida: después de todo, es trivial que el código ponga en un caso especial la última (o primera) línea. Los generadores de código se escriben una vez y se usan muchas veces.
fuente
Permite que cada línea siga la misma forma. En primer lugar, esto hace que sea más fácil agregar nuevas filas y que un sistema de control de versiones rastree el cambio de manera significativa y también le permite analizar el código más fácilmente. No puedo pensar en una razón técnica.
fuente
Esto está permitido para proteger de los errores causados por mover elementos en una larga lista.
Por ejemplo, supongamos que tenemos un código similar a este.
Y es genial, ya que muestra la trilogía original de los sitios de Stack Exchange.
Pero hay un problema con eso. Verá, el pie de página en este sitio web muestra Falla del servidor antes del Superusuario. Mejor arreglar eso antes de que alguien se dé cuenta.
Después de todo, mover las líneas no podría ser tan difícil, ¿verdad?
Lo sé, no hay un sitio web llamado "Server FaultSuper User", pero nuestro compilador afirma que existe. Ahora, el problema es que C tiene una función de concatenación de cadenas, que le permite escribir dos cadenas entre comillas dobles y concatenarlas sin usar nada (un problema similar también puede ocurrir con los enteros, ya que el
-
signo tiene múltiples significados).¿Y si la matriz original tuviera una coma inútil al final? Bueno, las líneas se moverían, pero ese error no habría sucedido. Es fácil perderse algo tan pequeño como una coma. Si recuerda poner una coma después de cada elemento de la matriz, tal error simplemente no puede suceder. No querrá perder cuatro horas depurando algo, hasta que encuentre que la coma es la causa de sus problemas .
fuente
Como muchas cosas, la coma final en un inicializador de matriz es una de las cosas que C ++ heredó de C (y tendrá que soportar para siempre). Una vista totalmente diferente de las que se encuentran aquí se menciona en el libro "Deep C secrets" .
Luego de un ejemplo con más de una "paradoja de coma":
leemos :
... para mí esto tiene más sentido
fuente
enum
caso es algo interesante, ya que ese es el caso en el que la coma faltante plantearía la menor ambigüedad. Dadostruct foo arr[] = {{1,2,3,4,5}, {3,4,5,6,7}, }
; Hay dos significados sensibles que el lenguaje podría asignar: crear una matriz de dos elementos o crear una matriz de tres elementos donde el último elemento tenga valores predeterminados. Si C hubiera adoptado la interpretación posterior, podría ver prohibidoenum foo {moe, larry, curly, };
en el principio de que solo debería haber una forma de escribir la declaración (sin la coma), pero ...enum foo {moe,,larry,curly,};
que se omite un número entremoe
ylarry
, generalmente no importaría si la coma final se procesó o se ignoró. El único caso en el que podría importar sería si el último elemento fuera el valor máximo para su tipo declarado, y eso ...Además de la generación de código y la facilidad de edición, si desea implementar un analizador sintáctico, este tipo de gramática es más simple y fácil de implementar. C # sigue esta regla en varios lugares en los que hay una lista de elementos separados por comas, como los elementos en una
enum
definición.fuente
Facilita la generación de código, ya que solo necesita agregar una línea y no necesita tratar de agregar la última entrada como si fuera un caso especial. Esto es especialmente cierto cuando se usan macros para generar código. Hay un impulso para tratar de eliminar la necesidad de macros del lenguaje, pero gran parte del lenguaje evolucionó de la mano con las macros disponibles. La coma adicional permite definir y usar macros como las siguientes:
Uso:
Es un ejemplo muy simplificado, pero a menudo las macros usan este patrón para definir cosas como mapas y tablas de despacho, mensaje, evento o traducción. Si no se permitía una coma al final, necesitaríamos un especial:
y eso sería muy incómodo de usar.
fuente
De modo que cuando dos personas agregan un nuevo elemento en una lista en ramas separadas, Git puede combinar los cambios correctamente, ya que Git funciona de forma lineal.
fuente
Si usa una matriz sin una longitud especificada, VC ++ 6.0 puede identificar automáticamente su longitud, por lo que si usa "int a [] = {1,2,};" la longitud de a es 3, pero la última no ' t inicializado, puedes usar "cout <
fuente