Lenguajes como C, Java, C ++ y todos requieren paréntesis alrededor de toda una expresión cuando se utiliza en una if
, while
o switch
.
if (true) {
// Do something
}
Opuesto a
if true {
// Do something
}
Esto me parece extraño porque los paréntesis son redundantes. En este ejemplo, true
es una sola expresión por sí sola. El paréntesis no transforma su significado de ninguna manera que yo sepa. ¿Por qué existe esta sintaxis extraña y por qué es tan común? ¿Hay algún beneficio que desconozca?
THEN
).if
declaración, solo crean una declaración compuesta.Respuestas:
Tiene que haber alguna forma de saber dónde termina la condición y comienza la rama. Hay muchas formas diferentes de hacerlo.
En algunos idiomas, no hay condicionales en absoluto , por ejemplo, en Smalltalk, Ser, la neolengua, Io, Ioke, Seph y Fancy. La ramificación condicional se implementa simplemente como un método normal como cualquier otro método. El método se implementa en objetos booleanos y se llama en un booleano. De esa manera, la condición es simplemente el receptor del método, y las dos ramas son dos argumentos, por ejemplo, en Smalltalk:
En caso de que esté más familiarizado con Java, esto es equivalente a lo siguiente:
En la familia de lenguajes Lisp, la situación es similar: los condicionales son solo funciones normales (en realidad, macros) y el primer argumento es la condición, el segundo y el tercer argumento son las ramas, por lo que son solo argumentos de funciones normales, y hay no se necesita nada especial para delimitarlos:
Algunos idiomas usan palabras clave como delimitadores, por ejemplo, Algol, Ada, BASIC, Pascal, Modula-2, Oberon, Oberon-2, Oberon activo, Componente Pascal, Zonnon, Modula-3:
En Ruby, puede usar una palabra clave o un separador de expresión (punto y coma o nueva línea):
Ir requiere que las ramas sean bloques y no permite expresiones o declaraciones, lo que hace que las llaves sean obligatorias. Por lo tanto, no se requieren paréntesis, aunque puede agregarlos si lo desea; Perl6 y Rust son similares a este respecto:
Algunos idiomas usan otros caracteres no alfanuméricos para delimitar la condición, por ejemplo, Python:
La conclusión es: necesita alguna forma de saber dónde termina la condición y comienza la rama. Hay muchas formas de hacerlo, los paréntesis son solo uno de ellos.
fuente
Los paréntesis solo son innecesarios si usa llaves.
Por ejemplo, se vuelve ambiguo sin ellos.
fuente
if
en: básico, ensamblaje, python, bash / zsh, tcl, batch, brainfuck o código de máquina. La falta de paréntesis solo hace que seaif
ambiguo si el lenguaje ha sido diseñado para depender de ellos.if Condition then ...
.{}
obligatorias y, por lo tanto, no requiere parens alrededor de la expresión. No solo no se requieren parens, sino que si recuerdo correctamente, agregarlos causaría un error de compilación, están prohibidosLos paréntesis en una
if
declaración no tienen el mismo significado que los paréntesis utilizados dentro de una expresión aritmética. Los paréntesis en una expresión aritmética se usan para agrupar expresiones. Los paréntesis en unaif
declaración se usan para delimitar la expresión booleana; es decir, diferenciar la expresión booleana del resto de laif
declaración.En una
if
declaración, los paréntesis no realizan una función de agrupación (aunque, dentro de laif
declaración, aún puede usar paréntesis para agrupar expresiones aritméticas. El conjunto externo de paréntesis sirve para delimitar la expresión booleana completa). Hacerlos necesarios simplifica el compilador, ya que el compilador puede confiar en que los paréntesis siempre estén ahí.fuente
IF primary_expression statement
. Tenga en cuenta que este último es igualmente inequívoco.primary_expression
no se puede distinguir de un operador de prefijo en una declaración de expresión. Para copiar la respuesta de Telastyn,if true ++ x;
. Además, si existen declaraciones vacías,if a & f;
puede ser una declaración vacía y binaria&
dentro de la condición, o una unaria&
al comienzo de la declaración. Pero cuando se combinan paréntesis, hay exactamente una coincidencia para la apertura (IDENTIFIER
,CONSTANT
,STRING_LITERAL
y'(' expression ')'
.Como otros ya han señalado parcialmente, esto se debe al hecho de que las expresiones también son declaraciones válidas, y en el caso de un bloque con solo una declaración, puede colocar llaves. Esto significa que lo siguiente es ambiguo:
Porque podría interpretarse como:
en lugar de:
Varios idiomas (p. Ej., Python) le permiten evitar el paréntesis pero aún tienen un marcador de condición final:
Sin embargo, tiene razón en que podríamos definir un lenguaje donde los paréntesis nunca sean necesarios: un lenguaje donde una expresión no sea una declaración válida no tendrá este problema.
Desafortunadamente, esto significa que cosas como:
que no sea afirmaciones válidas, por lo que habría que introducir una sintaxis extraña para poder llevar a cabo este tipo de acciones sin crear expresiones. Una manera simple de hacer esto es simplemente anteponer la expresión por un marcador como
[statement]
:Ahora la ambigüedad desaparece ya que tendrías que escribir:
Pero como puede ver, no veo que dicho lenguaje esté muy extendido ya que poner el paréntesis alrededor de una
if
condición (o una:
al final) es mucho mejor que poner ese marcador para cada declaración de expresión.Nota : el uso de un
[statement]
marcador es la sintaxis más simple que se me ocurre. Sin embargo, podría tener dos sintaxis completamente distintas para expresiones y declaraciones sin ambigüedad entre ellas, lo que no requeriría dicho marcador. El problema es: el lenguaje sería extremadamente extraño ya que para hacer las mismas cosas en una expresión o una declaración, tendría que usar una sintaxis completamente diferente.Una cosa que viene a la mente para tener dos sintaxis separadas sin un marcador tan explícito sería, por ejemplo: forzar declaraciones para usar símbolos unicode (así que en lugar de
for
usar una variación unicode de las letrasf
,o
yr
), mientras que las expresiones serán Solo ASCII.fuente
discard
su valor en Nim . Sin embargo, eso solo se hace por seguridad de tipo, no por razones sintácticas.?
simbol, de hecho, es una función después de PP). No hay ninguna;
. Claro, necesita un marcador para la línea de continuación, pero esto se desaconseja. harbour.github.io/doc/clc53.html#if-cmd . El compilador es rápido y simple (creado con Bison / Flex).if
,while
ecc son limitadas en comparación con las expresiones genéricas utilizadas en otros idiomas. Claro: si tiene más de dos categorías sintácticas (como enunciado, expresión, expresión lógica, expresión de café, ...) puede intercambiar cierta libertad.Es común que los lenguajes de la familia C requieran estos paréntesis, pero no son universales.
Uno de los cambios más notables sintácticas de Perl 6 es que la gramática modificada de modo que usted no tiene que dar los paréntesis alrededor
if
,for
y las condiciones de declaraciones similares. Entonces algo como esto es perfectamente válido en Perl 6:como es
Sin embargo, debido a que son solo expresiones, puede poner paréntesis alrededor de ellas si lo desea, en cuyo caso son solo agrupaciones ordinarias en lugar de una parte obligatoria de la sintaxis como están en C, C #, Java, etc.
Rust tiene una sintaxis similar a Perl 6 en este departamento:
Me parece que una característica de los lenguajes más modernos inspirados en C es mirar cosas como esta y preguntarse sobre cómo eliminarlas.
fuente
if
o de bucle con BLOCK, se requieren los parens, por ejemplo, enif ( $x == 4 ) { ... }
oforeach my $foo ( @bar ) { ... }
. Cuando se utiliza la notación postfix, los parens son opcionales, como enreturn unless $foo;
o++$x while s/foo/bar/g;
.Hay un aspecto que me sorprende que ninguna de las respuestas existentes haya mencionado.
C, y muchos derivados y similitudes de C, tienen una peculiaridad en que el valor de una asignación es el valor asignado. Una consecuencia de esto es que se puede usar una asignación donde se espera un valor.
Esto te permite escribir cosas como
o
o
(que se trata implícitamente como
while (n < m && *p1++ = *p2++ != 0) { n++; }
porque C trata a los no distintos de cero como verdaderos; por cierto, creo que se trata de strncpy () en la biblioteca estándar de C)o incluso
Y todo es válido. No todas las combinaciones sintácticamente válidas son necesariamente útiles (y los compiladores modernos advierten específicamente sobre las asignaciones dentro de los condicionales, porque es un error común), pero algunas de ellas son realmente útiles.
Analizar tales declaraciones probablemente sería mucho más difícil si no hubiera una forma inequívoca de determinar dónde comienza y termina la expresión condicional.
Los paréntesis ya se usaban para delimitar los nombres de las funciones de los argumentos de las funciones, por lo que creo que también parecían una opción natural para delimitar las palabras clave de los argumentos de las palabras clave.
Claro, se podrían definir sintaxis alternativas para hacer lo mismo. Pero hacerlo aumentaría la complejidad, particularmente en el analizador que luego necesitaría lidiar con dos conjuntos diferentes de sintaxis para la misma cosa. Cuando se estaba diseñando C, el poder de cómputo (tanto en términos de capacidad de cálculo de números, memoria de trabajo y capacidad de almacenamiento) era extremadamente limitado; Cualquier cosa que redujera la complejidad a un costo bajo o nulo para la legibilidad fue casi con certeza un cambio bienvenido.
El uso de paréntesis puede parecer un poco arcaico hoy en día, pero no es así dado que alguien con cierta familiaridad con el lenguaje, perjudica la legibilidad en comparación con otra sintaxis que es capaz de expresar las mismas cosas.
fuente
La razón es principalmente historia.
En el momento en que se escribió el primer compilador de C, las computadoras tenían ram, cpu y compiladores muy limitados, escritos "a mano" con pocas herramientas para ayudar a los escritores de compiladores. Por lo tanto , las reglas complejas eran costosas de implementar en un compilador. C ++, C #, Java, etc., fueron diseñados para que los programadores de C puedan aprender fácilmente, por lo tanto , no se realizaron cambios "innecesarios".
En los lenguajes 'c like' los condicionales (
if, while, etc
) no requieren unblock
código explícito , solo puede usar una declaración simple.o puede combinar declaraciones en una
compound statement
poniéndolas en{}
Nos gusta que el compilador encuentre el error que cometemos y que nos dé un mensaje de error que podamos entender.
fuente
Java y C ++ fueron desarrollados después de que C se había convertido en un lenguaje de programación muy popular. Una consideración en el diseño de cada uno de esos lenguajes fue que sería atractivo para los programadores de C y cortejaría a esos programadores para que usaran el nuevo lenguaje. (Fui uno de los programadores de C que cortejaron con éxito). C ++ además fue diseñado para ser (casi) intercambiable con el código de C. Para apoyar estos objetivos, tanto en C ++ y Java adoptaron gran parte de la sintaxis de C, incluyendo los paréntesis alrededor de las condiciones de
if
,while
yswitch
declaraciones.Por lo tanto, la razón por la cual todos estos lenguajes requieren paréntesis en torno a las condiciones de esas declaraciones es porque C sí, y la pregunta es realmente por qué C requiere esos paréntesis.
Los orígenes del lenguaje C se describen en este artículo por Dennis Ritchie, uno de los principales autores de su desarrollo (algunos incluso podrían decir el autor principal de su desarrollo). Como se dijo en ese artículo, C se desarrolló originalmente a principios de la década de 1970 como un lenguaje de programación de sistemas para computadoras con espacio extremadamente limitado en la memoria principal. Se deseaba tener un idioma que fuera de nivel superior al lenguaje ensamblador, pero dados los recursos disponibles para trabajar, la facilidad de analizar el idioma también era importante. Requerir los paréntesis facilitaría la identificación del código condicional.
También se podría inferir que la capacidad de escribir programas con menos caracteres se consideraba una ventaja, y dos paréntesis ocupan menos espacio que la palabra clave
THEN
que se usaba en FORTRAN y otros lenguajes de alto nivel en ese momento; de hecho, dado que los paréntesis también podían reemplazar espacios como delimitadores de símbolos,if(a==b)
era cuatro caracteres enteros más cortos queIF a==b THEN
.En cualquier caso, hubo que encontrar un equilibrio entre la facilidad con que los seres humanos podrían leer, escribir y comprender los programas escritos en C, la facilidad con que un compilador podría analizar y compilar programas escritos en C, y cuántos kilobytes (!) sería necesario tanto para la fuente del programa como para el compilador en sí. Y los paréntesis en torno a las condiciones de
if
,while
y lasswitch
declaraciones fue cómo la gente eligió lograr ese equilibrio en el diseño de C.Como se evidencia en varias otras respuestas, una vez que elimina las circunstancias particulares en las que se desarrolló C, se han utilizado todo tipo de sintaxis alternativas para los condicionales de varios lenguajes de programación. Entonces, los paréntesis realmente se reducen a una decisión de diseño que fue tomada por algunas personas bajo ciertas restricciones en un momento determinado de la historia.
fuente
Muchos aquí razonan que sin los paréntesis la sintaxis sería ambigua e implican en silencio que esto sería de alguna manera malo o incluso una situación imposible.
De hecho, los idiomas tienen muchas formas de lidiar con las ambigüedades. La precedencia del operador es solo una instancia de este tema.
No, la ambigüedad no es la razón de los paréntesis. Supongo que uno podría simplemente crear una versión de C que no requiera los paréntesis alrededor de la condición (haciéndolos opcionales) y que todavía cree un código válido en todos los casos. El ejemplo de
if a ++ b;
podría interpretarse como equivalente aif (a) ++b;
, oif (a++) b;
, lo que le parece más apropiado.La pregunta de por qué Dennis Ritchie eligió hacer que el () fuera obligatorio (y, por lo tanto, acuñar este meme para muchos idiomas derivados) es bastante lingüístico. Supongo que la noción de afirmar claramente que la condición es una expresión más que una orden fue el padre del pensamiento.
Y, de hecho, C fue diseñado para ser analizable mediante un analizador de una pasada. El uso de una sintaxis con paréntesis obligatorios alrededor de la condición respalda este aspecto.
fuente
if
No se requieren paréntesis en torno a las condiciones en Fortran, Cobol, PL / 1, Algol, Algo-68, Pascal, Modula, XPL, PL / M, MPL, ... o en cualquier otro idioma que tenga unathen
palabra clave.then
sirve para delimitarcondition
lo siguientestatement
.El paréntesis de cierre en C etc. funciona como
then
, y el de apertura es formalmente redundante.Las observaciones anteriores se aplican a los idiomas analizados tradicionalmente.
fuente