Expresión versus statement

Estoy preguntando sobre c #, pero supongo que es el mismo en la mayoría de los otros idiomas.

¿Alguien tiene una buena definición de expresiones y declaraciones y cuáles son las diferencias?

Expresión: algo que se evalúa como un valor. Ejemplo: 1 + 2 / x
Declaración: Una línea de código que hace algo. Ejemplo: GOTO 100

En los primeros lenguajes de progtwigción de propósito general, como FORTRAN, la distinción era clara como el cristal. En FORTRAN, una statement fue una unidad de ejecución, una cosa que hiciste. La única razón por la que no se llamaba “línea” era porque a veces abarcaba varias líneas. Una expresión en sí misma no podía hacer nada … tenías que asignarla a una variable.

1 + 2 / X

es un error en FORTRAN, porque no hace nada. Tuviste que hacer algo con esa expresión:

X = 1 + 2 / X

FORTRAN no tenía una gramática tal como la conocemos hoy en día: esa idea fue inventada, junto con la Forma Backus-Naur (BNF), como parte de la definición de Algol-60. En ese punto, la distinción semántica (“tener un valor” frente a “hacer algo”) estaba consagrada en la syntax : un tipo de frase era una expresión, y el otro una statement, y el analizador podía distinguirlas.

Los diseñadores de lenguajes posteriores difuminaron la distinción: permitieron que las expresiones sintácticas hicieran cosas, y permitieron declaraciones sintácticas que tenían valores. El ejemplo de lenguaje popular más antiguo que aún sobrevive es C. Los diseñadores de C se dieron cuenta de que no se hacía daño si se les permitía evaluar una expresión y descartar el resultado. En C, cada expresión sintáctica se puede convertir en una afirmación simplemente marcando un punto y coma a lo largo del final:

1 + 2 / x;

es una afirmación totalmente legítima, aunque no pasará absolutamente nada. Del mismo modo, en C, una expresión puede tener efectos secundarios , puede cambiar algo.

1 + 2 / callfunc(12);

porque callfunc podría hacer algo útil.

Una vez que permite que cualquier expresión sea una statement, también puede permitir que el operador de asignación (=) entre expresiones. Es por eso que C te permite hacer cosas como

callfunc(x = 2);

Esto evalúa la expresión x = 2 (asignando el valor de 2 a x) y luego pasa eso (el 2) a la función callfunc .

Este desenfoque de expresiones y afirmaciones ocurre en todas las derivadas C (C, C ++, C # y Java), que aún tienen algunas afirmaciones (como while ) pero que permiten que casi cualquier expresión se use como una statement (en asignación de C # solamente , las expresiones call, increment, y decrement se pueden usar como declaraciones, ver la respuesta de Scott Wisniewski ).

Tener dos “categorías sintácticas” (que es el nombre técnico para el tipo de declaraciones de cosas y expresiones) puede conducir a la duplicación de esfuerzos. Por ejemplo, C tiene dos formas de condicional, la forma de statement

 if (E) S1; else S2; 

y la forma de expresión

 E ? E1 : E2 

Y a veces la gente quiere duplicación que no está allí: en el estándar C, por ejemplo, solo una statement puede declarar una nueva variable local, pero esta capacidad es lo suficientemente útil como para que el comstackdor GNU C proporcione una extensión GNU que permita a una expresión declarar un variable local también.

A los diseñadores de otras lenguas no les gustó este tipo de duplicación, y vieron desde el principio que si las expresiones pueden tener efectos secundarios además de valores, entonces la distinción sintáctica entre enunciados y expresiones no es tan útil, así que se deshicieron de ella . Haskell, Icon, Lisp y ML son todos los idiomas que no tienen enunciados sintácticos, solo tienen expresiones. Incluso el bucle estructurado de clase y las formas condicionales se consideran expresiones, y tienen valores, pero no muy interesantes.

Me gustaría hacer una pequeña corrección a la respuesta de Joel anterior.

C # no permite que todas las expresiones se utilicen como declaraciones. En particular, solo las expresiones de asignación, llamada, incremento y decremento se pueden usar como declaraciones.

Por ejemplo, el comstackdor C # marcará el siguiente código como un error de syntax:

1 + 2;

  • una expresión es cualquier cosa que arroje un valor: 2 + 2
  • una statement es uno de los “bloques” básicos de la ejecución del progtwig.

Tenga en cuenta que en C, “=” es en realidad un operador, que hace dos cosas:

  • devuelve el valor de la subexpresión de la mano derecha.
  • copia el valor de la subexpresión de la mano derecha en la variable en el lado izquierdo.

Aquí hay un extracto de la gramática ANSI C. Puede ver que C no tiene muchos tipos diferentes de enunciados … la mayoría de los enunciados en un progtwig son enunciados de expresión, es decir, una expresión con un punto y coma al final.

 statement : labeled_statement | compound_statement | expression_statement | selection_statement | iteration_statement | jump_statement ; expression_statement : ';' | expression ';' ; 

http://www.lysator.liu.se/c/ANSI-C-grammar-y.html

Una expresión es algo que devuelve un valor, mientras que una statement no.

Por ejemplo:

 1 + 2 * 4 * foo.bar() //Expression foo.voidFunc(1); //Statement 

El gran acuerdo entre los dos es que puedes encadenar expresiones juntas, mientras que las declaraciones no pueden encadenarse.

Puede encontrar esto en wikipedia , pero las expresiones se evalúan con algún valor, mientras que las declaraciones no tienen valor evaluado.

Por lo tanto, las expresiones se pueden usar en declaraciones, pero no al revés.

Tenga en cuenta que algunos lenguajes (como Lisp, y creo que Ruby, y muchos otros) no diferencian statement contra expresión … en tales idiomas, todo es una expresión y puede encadenarse con otras expresiones.

Para una explicación de las diferencias importantes en la compibilidad (chainable) de expresiones vs declaraciones, mi referencia favorita es el documento de premiación Turing de John Backus, ¿Se puede liberar la progtwigción del estilo de von Neumann? .

Los lenguajes imperativos (Fortran, C, Java, …) enfatizan enunciados para la estructuración de progtwigs y tienen expresiones como una especie de pensamiento posterior. Los lenguajes funcionales enfatizan las expresiones. Los lenguajes puramente funcionales tienen expresiones tan potentes que las declaraciones pueden eliminarse del todo.

Simplemente: una expresión evalúa a un valor, una statement no.

Las expresiones se pueden evaluar para obtener un valor, mientras que las declaraciones no devuelven un valor (son de tipo vacío ).

Las expresiones de llamada de función también se pueden considerar como instrucciones de curso, pero a menos que el entorno de ejecución tenga una variable incorporada especial para contener el valor devuelto, no hay forma de recuperarlo.

Los lenguajes orientados a enunciados requieren que todos los procedimientos sean una lista de enunciados. Los lenguajes orientados a expresiones, que probablemente son todos los lenguajes funcionales, son listas de expresiones, o en el caso de LISP, una expresión S larga que representa una lista de expresiones.

Aunque ambos tipos se pueden componer, la mayoría de las expresiones se pueden componer arbitrariamente siempre que los tipos coincidan. Cada tipo de statement tiene su propia forma de componer otras declaraciones, si pueden hacer eso todas. Las declaraciones Foreach y if requieren una sola statement o que todas las declaraciones subordinadas van en un bloque de instrucción, una después de otra, a menos que las subclasificaciones permitan sus propias subestaciones.

Las declaraciones también pueden incluir expresiones, donde una expresión realmente no incluye ninguna statement. Una excepción, sin embargo, sería una expresión lambda, que representa una función, y puede incluir cualquier cosa que una función pueda incluir a menos que el lenguaje solo permita lambdas limitadas, como la lambda de una sola expresión de Python.

En un lenguaje basado en expresiones, todo lo que necesita es una expresión única para una función, ya que todas las estructuras de control devuelven un valor (muchas de ellas devuelven NIL). No es necesario un enunciado de retorno ya que la última expresión evaluada en la función es el valor de retorno.

Algunas cosas sobre los lenguajes basados ​​en expresiones:


Lo más importante: todo devuelve un valor


No hay diferencia entre llaves y llaves para delimitar bloques de código y expresiones, ya que todo es una expresión. Sin embargo, esto no impide el scope léxico: se podría definir una variable local para la expresión en la que está contenida su definición y todas las declaraciones contenidas dentro de esa, por ejemplo.


En un lenguaje basado en expresión, todo devuelve un valor. Esto puede ser un poco extraño al principio – ¿Qué hace (FOR i = 1 TO 10 DO (print i)) regresar?

Algunos ejemplos simples:

  • (1) devuelve 1
  • (1 + 1) devuelve 2
  • (1 == 1) devuelve TRUE
  • (1 == 2) devuelve FALSE
  • (IF 1 == 1 THEN 10 ELSE 5) devuelve 10
  • (IF 1 == 2 THEN 10 ELSE 5) devuelve 5

Un par de ejemplos más complejos:

  • Algunas cosas, como algunas llamadas a funciones, en realidad no tienen un valor significativo para devolver (¿Cosas que solo producen efectos secundarios?). Llamar a OpenADoor(), FlushTheToilet() o TwiddleYourThumbs() devolverá algún tipo de valor mundano, como OK, Done o Success.
  • Cuando se evalúan expresiones desvinculadas múltiples dentro de una expresión más grande, el valor de la última cosa evaluada en la expresión grande se convierte en el valor de la expresión grande. Para tomar el ejemplo de (FOR i = 1 TO 10 DO (print i)) , el valor del bucle for es “10”, hace que la expresión (print i) se evalúe 10 veces, cada vez que se devuelve i como cuerda. El tiempo final a través de devoluciones 10 , nuestra respuesta final

A menudo requiere un ligero cambio de mentalidad para aprovechar al máximo un lenguaje basado en expresiones, ya que el hecho de que todo sea una expresión permite “en línea” muchas cosas.

Como un ejemplo rápido:

  FOR i = 1 to (IF MyString == "Hello, World!" THEN 10 ELSE 5) DO ( LotsOfCode ) 

es un reemplazo perfectamente válido para la no basada en la expresión

 IF MyString == "Hello, World!" THEN TempVar = 10 ELSE TempVar = 5 FOR i = 1 TO TempVar DO ( LotsOfCode ) 

En algunos casos, el diseño que permite el código basado en expresiones me parece mucho más natural

Por supuesto, esto puede conducir a la locura. Como parte de un proyecto de hobby en un lenguaje de scripting basado en expresiones llamado MaxScript, logré llegar a esta línea de monstruos

 IF FindSectionStart "rigidifiers" != 0 THEN FOR i = 1 TO (local rigidifier_array = (FOR i = (local NodeStart = FindsectionStart "rigidifiers" + 1) TO (FindSectionEnd(NodeStart) - 1) collect full_array[i])).count DO ( LotsOfCode ) 

Una statement es un caso especial de una expresión, uno con tipo de void . La tendencia de los idiomas a tratar las declaraciones de manera diferente a menudo causa problemas, y sería mejor si se generalizaran adecuadamente.

Por ejemplo, en C # tenemos el muy útil conjunto de delegates generics Func sobrecargados. Pero también tenemos que tener una Action correspondiente Action establecida, y la progtwigción de alto orden de propósito general constantemente tiene que ser duplicada para tratar con esta desafortunada bifurcación.

Ejemplo trivial: una función que verifica si una referencia es nula antes de llamar a otra función:

 TResult IfNotNull(TValue value, Func func) where TValue : class { return (value == null) ? default(TValue) : func(value); } 

¿Podría el comstackdor lidiar con la posibilidad de que TResult sea void ? Sí. Todo lo que tiene que hacer es requerir que el retorno sea seguido por una expresión que sea de tipo void . El resultado del default(void) sería de tipo void , y el func que se transfiere debería ser de la forma Func (que sería equivalente a Action ).

Varias otras respuestas implican que no se pueden entablar declaraciones como se puede con expresiones, pero no estoy seguro de dónde viene esta idea. Podemos pensar en el ; que aparece después de los enunciados como operador infijo binario, tomando dos expresiones de tipo void y combinándolas en una sola expresión de tipo void .

Declaraciones -> Instrucciones a seguir secuencialmente
Expresiones -> Evaluación que devuelve un valor

Las declaraciones son básicamente como pasos o instrucciones en un algoritmo, el resultado de la ejecución de una instrucción es la actualización del puntero de instrucción (llamado ensamblador)

Las expresiones no implican orden de ejecución a primera vista, su propósito es evaluar y devolver un valor. En los lenguajes de progtwigción imperativos, la evaluación de una expresión tiene un orden, pero es solo por el modelo imperativo, pero no es su esencia.

Ejemplos de declaraciones:

 for goto return if 

(todos ellos implican el avance de la línea (statement) de ejecución a otra línea)

Ejemplo de expresiones:

 2+2 

(no implica la idea de ejecución, sino de la evaluación)

Las declaraciones son oraciones gtwigticalmente completas. Las expresiones no son Por ejemplo

 x = 5 

dice “x obtiene 5” Esta es una oración completa. El código

 (x + 5)/9.0 

lee, “x más 5 dividido por 9.0”. Esta no es una oración completa. La statement

 while k < 10: print k k += 1 

es una oración completa. Observe que el encabezado del bucle no es; "mientras k <10" es una cláusula subordinada.

Declaración ,

Una statement es un bloque de construcción procedimental a partir del cual se construyen todos los progtwigs de C #. Una statement puede declarar una variable local o constante, llamar a un método, crear un objeto o asignar un valor a una variable, propiedad o campo.

Una serie de instrucciones rodeadas de llaves forman un bloque de código. Un cuerpo de método es un ejemplo de un bloque de código.

 bool IsPositive(int number) { if (number > 0) { return true; } else { return false; } } 

Las declaraciones en C # a menudo contienen expresiones. Una expresión en C # es un fragmento de código que contiene un valor literal, un nombre simple o un operador y sus operandos.

Expresión ,

Una expresión es un fragmento de código que se puede evaluar con un único valor, objeto, método o espacio de nombres. Los dos tipos más simples de expresiones son literales y nombres simples. Un literal es un valor constante que no tiene nombre.

 int i = 5; string s = "Hello World"; 

Ambos i y s son nombres simples que identifican variables locales. Cuando esas variables se usan en una expresión, el valor de la variable se recupera y se usa para la expresión.

Prefiero el significado de statement en el sentido lógico formal de la palabra. Es uno que cambia el estado de una o más de las variables en el cálculo, permitiendo que se haga una statement verdadera o falsa sobre su valor (es).

Supongo que siempre habrá confusión en el mundo de la informática y en la ciencia en general cuando se introducen nuevas terminologías o palabras, las palabras existentes son ‘reutilizadas’ o los usuarios ignoran la terminología existente, establecida o ‘propia’ de lo que están describiendo

No estoy realmente satisfecho con ninguna de las respuestas aquí. Miré la gramática para C ++ (ISO 2008) . Sin embargo, tal vez por el bien de la didáctica y la progtwigción, las respuestas podrían ser suficientes para distinguir los dos elementos (sin embargo, la realidad parece más complicada).

Una statement consta de cero o más expresiones, pero también pueden ser otros conceptos de lenguaje. Esta es la forma Extended Backus Naur para la gramática (extracto de la statement):

 statement: labeled-statement expression-statement <-- can be zero or more expressions compound-statement selection-statement iteration-statement jump-statement declaration-statement try-block 

Podemos ver los otros conceptos que se consideran enunciados en C ++.

  • expression-statement s es autoexplicativo (una statement puede consistir en cero o más expresiones, leer la gramática con cuidado, es complicado)
  • case por ejemplo, es una statement etiquetada
  • los enunciados de selección son if if/else , case
  • iteration-statement s son while , do...while , for (...)
  • Los enunciados de salto s son break , continue , return (puede devolver la expresión), goto
  • statement-statement es el conjunto de declaraciones
  • try-block es una statement que representa bloques try/catch
  • y puede haber algo más en la gramática

Este es un extracto que muestra la parte de expresiones:

 expression: assignment-expression expression "," assignment-expression assignment-expression: conditional-expression logical-or-expression assignment-operator initializer-clause throw-expression 
  • las expresiones son o contienen a menudo asignaciones
  • expresión condicional (sonidos engañosos) se refiere al uso de los operadores ( + , - , * , / , & , | , && , || , ...)
  • throw-expression - ¿eh? la cláusula throw es una expresión también

Aquí está el resumen de una de las respuestas más simples que encontré.

Respondido originalmente por Anders Kaseorg

Una statement es una línea completa de código que realiza alguna acción, mientras que una expresión es cualquier sección del código que se evalúa como un valor.

Las expresiones se pueden combinar “horizontalmente” en expresiones más grandes usando operadores, mientras que las declaraciones solo se pueden combinar “verticalmente” escribiendo una tras otra, o con construcciones de bloques.

Cada expresión se puede usar como una statement (cuyo efecto es evaluar la expresión e ignorar el valor resultante), pero la mayoría de las declaraciones no se pueden usar como expresiones.

http://www.quora.com/Python-programming-language-1/Whats-the-difference-between-a-statement-and-an-expression-in-Python

Para mejorar y validar mi respuesta anterior, las definiciones de los términos del lenguaje de progtwigción deben explicarse a partir de la teoría de tipos de ciencias de la computación cuando corresponda.

Una expresión tiene un tipo distinto del tipo Inferior, es decir, tiene un valor. Una statement tiene el tipo de Unidad o Inferior.

De esto se desprende que una statement solo puede tener algún efecto en un progtwig cuando crea un efecto secundario, porque no puede devolver un valor o solo devuelve el valor del tipo de Unidad que es no asignable (en algunos idiomas como un void de C) o (como en Scala) puede almacenarse para una evaluación retrasada de la statement.

Obviamente, @pragma o a /*comment*/ no tienen ningún tipo y, por lo tanto, se diferencian de los enunciados. Por lo tanto, el único tipo de enunciado que no tendría efectos secundarios sería una no operación. La no operación solo es útil como marcador de posición para futuros efectos secundarios. Cualquier otra acción debido a una statement sería un efecto secundario. De nuevo, una pista del comstackdor, por ejemplo @pragma , no es una statement porque no tiene ningún tipo.

Más precisamente, una statement debe tener un “efecto secundario” (es decir, ser imperativo ) y una expresión debe tener un tipo de valor (es decir, no el tipo de fondo).

El tipo de una statement es el tipo de unidad, pero debido a la unidad de detención de teorema es ficción, digamos el tipo de letra de abajo .


Void no es precisamente el tipo de fondo (no es el subtipo de todos los tipos posibles). Existe en idiomas que no tienen un sistema de tipo completamente sonoro . Eso puede sonar como una statement esnob, pero la completitud , como las anotaciones de varianza, son fundamentales para escribir software extensible.

Veamos qué tiene que decir Wikipedia sobre este asunto.

https://en.wikipedia.org/wiki/Statement_(computer_science)

En la progtwigción de computadoras, una statement es el elemento autónomo más pequeño de un lenguaje de progtwigción imperativo que expresa alguna acción que se debe llevar a cabo.

Muchos idiomas (por ejemplo, C) hacen una distinción entre enunciados y definiciones, con una statement que solo contiene código ejecutable y una definición que declara un identificador, mientras que una expresión evalúa solo un valor.