views:

6668

answers:

13

I'm asking with regards to c#, but I assume its the same in most other languages.

Does anyone have a good definition of expressions and statements and what the differences are.

Thanks in advance.

+1  A: 

Expressions can be evaluated to get a value, whereas statements don't return a value (they're of type void).

Function call expressions can also be considered statements of course, but unless the execution environment has a special built-in variable to hold the returned value, there is no way to retrieve it.

Statement-oriented languages require all procedures to be a list of statements. Expression-oriented languages, which is probably all functional languages, are lists of expressions, or in tha case of LISP, one long S-expression that represents a list of expressions.

Although both types can be composed, most expressions can be composed arbitrarily as long as the types match up. Each type of statement has its own way of composing other statements, if they can do that all. Foreach and if statements require either a single statment or that all subordinate statements go in a statement block, one after another, unless the substatements allow for thier own substatements.

Statements can also include expressions, where an expression doesn't really include any statements. One exception, though, would be a lambda expression, which represents a function, and so can include anything a function can iclude unless the language only allows for limited lambdas, like Python's single-expression lambdas.

In an expression-based language, all you need is a single expression for a function since all control structures return a value (a lot of them return NIL). There's no need for a return statement since the last-evaluated expression in the function is the return value.

Mark Cidade
+6  A: 

An expression is something that returns a value, whereas a statement does not.

For examples:

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

The Big Deal between the two is that you can chain expressions together, whereas statements cannot be chained.

Patrick
Sure statements can be chained. {stmt1; stmt2; stmt3;} is a chain, and it's also a (compound) statement itself.
Hugh Allen
`foo.voidFunc(1);` is an expression with a void value. `while` and `if` are statements.
ΤΖΩΤΖΙΟΥ
+1  A: 

Simply: an expression evaluates to a value, a statement doesn't.

Matthew Schinckel
+4  A: 

You can find this on wikipedia, but expressions are evaluated to some value, while statements have no evaluated value.

Thus, expressions can be used in statements, but not the other way around.

Note that some languages (such as Lisp, and I believe Ruby, and many others) do not differentiate statement vs expression... in such languages, everything is an expression and can be chained with other expressions.

Mike Stone
+143  A: 
Joel Spolsky
Thanks for a very clear answer.
DrG
If I'm not mis-interpreting you here, you seem to claim that "(setf (third foo) 'goose)" is an expression, not a statement, both because it's Lisp, which "doesn't have statements," and because Lisp is more than a decade older than C, which was the "earliest popular language to blur the lines [between expressions and statements]." Could explain the details of that to me?
Curt Sampson
Damn, I'm curious about that also, but I guess the answer is too old to get attention.
Carson Myers
@Curt Sampson, have you asked that as a separate question?
Kelly French
@curt, @Carson, @Kelly: I've updated to try to explain details.
Norman Ramsey
+6  A: 
  • an expression is anything that yields a value: 2 + 2
  • a statement is one of the basic "blocks" of program execution.

Note that in C, "=" is actually an operator, which does two things:

  • returns the value of the right hand subexpression.
  • copies the value of the right hand subexpression into the variable on the left hand side.

Here's an extract from the ANSI C grammar. You can see that C doesn't have many different kinds of statements... the majority of statements in a program are expression statements, i.e. an expression with a semicolon at the end.

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

Mark Harrison
+16  A: 

I would like to make a small correction to Joel's answer above.

C# does not allow all expressions to be used as statements. In particular, only assignment, call, increment, and decrement expressions may be used as statements.

For example, the C# compiler will flag the following code as a syntax error:

1 + 2;

Scott Wisniewski
You mean "every", not "any".
Blindy
"Every" is correct. "Just any" is also correct, but "any" would imply that all expressions are not allowed as statements, which is factually incorrect and not the intended meaning.
Justice
A: 

An expression is a noun. A statement is a sentence: a verb acting on one or more nouns.

Dov Wasserman
+2  A: 

Rather than thinking of statements, I think of void expressions, hehe... Oh, I've been drinking too much. :)

+3  A: 

Some things about expression based languages:


Most important: Everything returns an value


There is no difference between curly brackets and braces for delimiting code blocks and expressions, since everything is an expression. This doesn't prevent lexical scoping though: A local variable could be defined for the expression in which its definition is contained and all statements contained within that, for example.


In an expression based language, everything returns a value. This can be a bit strange at first -- What does (FOR i = 1 TO 10 DO (print i)) return?

Some simple examples:

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

A couple more complex examples:

  • Some things, such as some function calls, don't really have a meaningful value to return (Things that only produce side effects?). Calling OpenADoor(), FlushTheToilet() or TwiddleYourThumbs() will return some sort of mundane value, such as OK, Done, or Success.
  • When multiple unlinked expressions are evaluated within one larger expression, the value of the last thing evaluated in the large expression becomes the value of the large expression. To take the example of (FOR i = 1 TO 10 DO (print i)), the value of the for loop is "10", it causes the (print i) expression to be evaluated 10 times, each time returning i as a string. The final time through returns 10, our final answer


It often requires a slight change of mindset to get the most out of an expression based language, since the fact that everything is an expression makes it possible to 'inline' a lot of things

As a quick example:

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

is a perfectly valid replacement for the non expression-based

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

In some cases, the layout that expression-based code permits feels much more natural to me

Of course, this can lead to madness. As part of a hobby project in an expression-based scripting language called MaxScript, I managed to come up with this monster line

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
)
+1  A: 

A statement is a special case of an expression, one with void type. The tendency of languages to treat statements differently often causes problems, and it would be better if they were properly generalized.

For example, in C# we have the very useful Func<T1, T2, T3, TResult> overloaded set of generic delegates. But we also have to have a corresponding Action<T1, T2, T3> set as well, and general purpose higher-order programming constantly has to be duplicated to deal with this unfortunate bifurcation.

Trivial example - a function that checks whether a reference is null before calling onto another function:

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

Could the compiler deal with the possibility of TResult being void? Yes. All it has to do is require that return is followed by an expression that is of type void. The result of default(void) would be of type void, and the func being passed in would need to be of the form Func<TValue, void> (which would be equivalent to Action<TValue>).

A number of other answers imply that you can't chain statements like you can with expressions, but I'm not sure where this idea comes from. We can think of the ; that appears after statements as a binary infix operator, taking two expressions of type void and combining them into a single expression of type void.

Daniel Earwicker
+2  A: 

For an explanation of important differences in composability (chainability) of expressions vs statements, my favorite reference is John Backus's Turing award paper, Can programming be liberated from the von Neumann style?.

Imperative languages (Fortran, C, Java, ...) emphasize statements for structuring programs, and have expressions as a sort of after-thought. Functional languages emphasize expressions. Purely functional languages have such powerful expressions than statements can be eliminated altogether.

Conal
A: 

Very clear explanation is given on the MSDN, starting from Statements, Expressions, and Operators, especially on page about Statements (switch to C# tab for code examples).

The actions that a program takes are expressed in statements. Common actions include declaring variables, assigning values, calling methods, looping through collections, and branching to one or another block of code, depending on a given condition. The order in which statements are executed in a program is called the flow of control or flow of execution. The flow of control may vary every time that a program is run, depending on how the program reacts to input that it receives at run time.

A statement can consist of a single line of code that ends in a semicolon, or a series of single-line statements in a block. A statement block is enclosed in {} brackets and can contain nested blocks.

Roman Boiko