Expression versus Statement
Asked Answered
E

21

480

I'm asking with regards to C#, but I assume it's the same in most other languages.

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

Eraste answered 21/8, 2008 at 0:28 Comment(7)
I find the answer you chose to be ambiguous. An expression also does something-- it evaluates to a value. I provided a non-ambiguous answer.Policyholder
@ShelbyMooreIII - Non-ambiguous and also wrong. The accepted answer is worded in an informal way, but that wording makes it easy to understand--and most importantly, the meaning it conveys is accurate.Ploughman
@JustinMorgan Sadly, the definitions in the accepted answer are also obviously wrong ("evaluates to a value"/"a line of code") for most contemporary language include C-like ones: expressions can be used in unevaluated contexts and statements have nothing to do with lines. Even there are some explanations, the short answer is confusing and misleading.Pritchett
To add - the question is actually a false dichotomy. Expressions have the property of being evaluatable, statements too but aren't expected to feed into anything, and c# supports the concept of ExpressionStatement, eg a=b as opposed to c=(a=b),, which is an expression that does not return a value. Whether you call an ExpressionStatement a Statement or an Expression is up to you.Maag
It's also worth noting that expressions have side effects. If you are evaluating a binary expression eg (a+b) and a is a property getter that sets the value of b, then you need to know that the binary expression is being evaluated left to right.Maag
So the end result really is that whether something is an expression or a statement is simply the context: whether something places the expectation of an output.Maag
you can see also this answer https://mcmap.net/q/16678/-difference-between-an-expression-and-statement-in-dartSmiga
M
585

Expression: Something which evaluates to a value. Example: 1+2/x
Statement: A line of code which does something. Example: GOTO 100

In the earliest general-purpose programming languages, like FORTRAN, the distinction was crystal-clear. In FORTRAN, a statement was one unit of execution, a thing that you did. The only reason it wasn't called a "line" was because sometimes it spanned multiple lines. An expression on its own couldn't do anything... you had to assign it to a variable.

1 + 2 / X

is an error in FORTRAN, because it doesn't do anything. You had to do something with that expression:

X = 1 + 2 / X

FORTRAN didn't have a grammar as we know it today—that idea was invented, along with Backus-Naur Form (BNF), as part of the definition of Algol-60. At that point the semantic distinction ("have a value" versus "do something") was enshrined in syntax: one kind of phrase was an expression, and another was a statement, and the parser could tell them apart.

Designers of later languages blurred the distinction: they allowed syntactic expressions to do things, and they allowed syntactic statements that had values. The earliest popular language example that still survives is C. The designers of C realized that no harm was done if you were allowed to evaluate an expression and throw away the result. In C, every syntactic expression can be a made into a statement just by tacking a semicolon along the end:

1 + 2 / x;

is a totally legit statement even though absolutely nothing will happen. Similarly, in C, an expression can have side-effects—it can change something.

1 + 2 / callfunc(12);

because callfunc might just do something useful.

Once you allow any expression to be a statement, you might as well allow the assignment operator (=) inside expressions. That's why C lets you do things like

callfunc(x = 2);

This evaluates the expression x = 2 (assigning the value of 2 to x) and then passes that (the 2) to the function callfunc.

This blurring of expressions and statements occurs in all the C-derivatives (C, C++, C#, and Java), which still have some statements (like while) but which allow almost any expression to be used as a statement (in C# only assignment, call, increment, and decrement expressions may be used as statements; see Scott Wisniewski's answer).

Having two "syntactic categories" (which is the technical name for the sort of thing statements and expressions are) can lead to duplication of effort. For example, C has two forms of conditional, the statement form

if (E) S1; else S2;

and the expression form

E ? E1 : E2

And sometimes people want duplication that isn't there: in standard C, for example, only a statement can declare a new local variable—but this ability is useful enough that the GNU C compiler provides a GNU extension that enables an expression to declare a local variable as well.

Designers of other languages didn't like this kind of duplication, and they saw early on that if expressions can have side effects as well as values, then the syntactic distinction between statements and expressions is not all that useful—so they got rid of it. Haskell, Icon, Lisp, and ML are all languages that don't have syntactic statements—they only have expressions. Even the class structured looping and conditional forms are considered expressions, and they have values—but not very interesting ones.

Mckissick answered 21/8, 2008 at 2:17 Comment(8)
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?Cyrano
@Curt Sampson, have you asked that as a separate question?Pacificas
If I'm not mistaken, callfunc(x = 2); passes x to callfunc, not 2. If x is a float, callfunc(float) will be called, not callfunc(int). And in C++, if you pass x=y to func, and func takes a reference and changes it, it changes x, not y.Looselimbed
In the answer above, it is written that "Haskell,... are all languages that don't have syntactic statements - they only have expressions". I am curious why where clause in haskell is considered an expression and not a statement. learnyouahaskell.com/syntax-in-functions#whereLadoga
@Ladoga I believe where is actually a part of function declaration, not expression or statement.Kigali
@JimBalter I have read the reference grammar, and actually I was right. haskell.org/onlinereport/haskell2010/haskellch10.html. Notice that where clause is treated as a part of rhs (The right-hand side of the declaration), not an exp (Expression). Claiming where as expression implies guards are an expression, too.Kigali
@Akangka My comment had nothing to do with yours ... it was about this answer from Joel Spolsky.Kodiak
you can see also this answer https://mcmap.net/q/16678/-difference-between-an-expression-and-statement-in-dartSmiga
C
26
  • 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

Cholon answered 21/8, 2008 at 5:5 Comment(1)
Incorrect logic on what a statement is. A declarative program can also execute, but a declarative program has no statements. A statement is and does "side-effects", i.e. is imperative. cf. my answer.Policyholder
U
16

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.

Upandcoming answered 21/8, 2008 at 0:30 Comment(5)
Sure statements can be chained. {stmt1; stmt2; stmt3;} is a chain, and it's also a (compound) statement itself.Mydriatic
foo.voidFunc(1); is an expression with a void value. while and if are statements.Kubetz
I'm curious about the non-chaining of statements. Would something like "if (x > 1) return;" be considered to be chaining two statements together?Impatience
@SimonTewsi I believe the return is considered a substatement.Paradigm
@SimonTewsi The return statement here is implicitly inside the if statement's block, so it is part of the if statement, not chained with it. The compiler allows us to omit the braces here, since it is a single line block.Kate
T
11

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.

Tiltyard answered 21/8, 2008 at 0:35 Comment(0)
C
9

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.

Condorcet answered 23/6, 2009 at 20:49 Comment(0)
N
7

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.

Nimbus answered 21/8, 2008 at 0:30 Comment(13)
The type of a statement is the bottom type. Void is not the bottom type. See my answer.Policyholder
Isn't the null type the bottom type (single value of null)? Wouldn't void be more like the unit type (but with its single value inaccessible)?Nimbus
If void is the return type of a function that never returns (e.g. a function that throws an error), it is the bottom type. Otherwise void is the unit type. You are correct that a statement that can't diverge, has the unit type. But a statement that can diverge is the bottom type. Due to the Halting Theorem, we usually can't prove that a function doesn't diverge, so I think unit is fiction. The bottom type can't have a value, so it can't have a single value of null.Policyholder
Regarding what I said three years ago, I don't know if I still think of statements as having a void type or any type really. In the statement-based languages with which I'm familiar, only values and anything that either stores or returns a value (e.g., expressions, variables, members, and functions) can have types. I generally think of the bottom type as the empty set (no values) and so anything that doesn't exist ontologically would have this type. A null value is really a pseudovalue denoting that a reference refers to something that doesn't exist.Nimbus
Mark I appreciated the rationality of your response. You basically took the words out of my mouth And I hope it was clear that I admitted to you that you were correct to raise the unit point. I think we agree. I wasn't going to bother mentioning this, but it seems that some people here think I am being negative. I am just trying to be factual.Policyholder
@ShelbyMooreIII No, it is not. A statement simply doesn't have a type. Attempt to treat it as value is a syntax error. If the expression have a bottom type, it will never return anything. It will throw an exception, doing an infinite loop, or changes the control flow in other funky ways.Kigali
@Akangka in type theory all code fragments (not to be conflated with comments, pragmas, preprocessor macros, etc) have a type otherwise the type system wouldn’t be coherent. If your PL (which isn’t for example Scala) doesn’t allow you to abstract over the Unit type doesn’t negate the fact (as I wrote in my correct answers) that statements aren’t expressions (i.e. don’t return a value) thus have the Unit type. I also explained in my answer that Unit is arguably fiction thus IMO synonymous with the bottom type. A code fragment which has the type of bottom isn’t an expression…Policyholder
@Akangka the problem here on S.O. as I elaborated by example is groupthink wants to conflate separate-concerns from distinct models. For example as I correctly explained in my heavily downvoted answers on this page, if expression is so defined as to allow the bottom type and/or side-effects then the term expression would be definitionally indistinct w.r.t. term statement, because statements have side-effects and diverge (i.e. never return).Policyholder
@Akangka wrote “A statement simply doesn't have a type […] If the expression have a bottom type”. Don’t delete your comment when you realize that statements can invoke expressions. Lol. I archived the discussion.Policyholder
@ShelbyMooreIII "in type theory all code fragments [...] have a type otherwise the type system wouldn’t be coherent." Yeah, you're right... in a language in a big family of typed lambda calculus, which is the most widely used mathematical model for programming language. For most of statement (except variable definition, and probably few others), you can also define an expression let expr = ()=>{ statement; } in expr() which is an expression. The reason of why typed lambda calculus has no statements, is because 1. statements are unnecessary and 2. it complicates reasoning unnecessarily.Kigali
@ShelbyMooreIII In fact, type is actually just a set of what value an expression might return (if at all). In all type system that have a function (even if not first class), if I have a function f of type (Unit) -> a, I should be able to enter f(<anything that have type of Unit>). However, in Python, you can't do f(raise Exception("this expression should've been legal")) and in Rust, you can't do f(let a = 42). This syntax has no equivalents in typed lambda calculus.Kigali
@ShelbyMooreIII If you think statement as having a bottom type, the point still stands because the bottom type is a subtype of every type. Also, I didn't delete the commentKigali
Let us continue this discussion in chat.Kigali
T
7

I am not really satisfied with any of the answers here. I looked at the grammar for C++ (ISO 2008). However maybe for the sake of didactics and programming the answers might suffice to distinguish the two elements (reality looks more complicated though).

A statement consists of zero or more expressions, but can also be other language concepts. This is the Extended Backus Naur form for the grammar (excerpt for statement):

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

We can see the other concepts that are considered statements in C++.

  • expression-statements is self-explaining (a statement can consist of zero or more expressions, read the grammar carefully, it's tricky)
  • case for example is a labeled-statement
  • selection-statements are if if/else, case
  • iteration-statements are while, do...while, for (...)
  • jump-statements are break, continue, return (can return expression), goto
  • declaration-statement is the set of declarations
  • try-block is statement representing try/catch blocks
  • and there might be some more down the grammar

This is an excerpt showing the expressions part:

expression:
        assignment-expression
        expression "," assignment-expression
assignment-expression:
        conditional-expression
        logical-or-expression assignment-operator initializer-clause
        throw-expression
  • expressions are or contain often assignments
  • conditional-expression (sounds misleading) refers to usage of the operators (+, -, *, /, &, |, &&, ||, ...)
  • throw-expression - uh? the throw clause is an expression too
Tremaine answered 21/6, 2015 at 0:56 Comment(1)
I recently started taking an interest in this topic, and as is unfortunately so often the case on stackoverflow, this low voted answer is probably the only 'correct' one in the list. Simply, 'a=b' can be either an expression or statement depending on the context. In other words it isnt some intrinsic property of the syntax element that determines expression vs statement but the context as defined by a grammar, implied or explicit, used by the compiler.Maag
N
5

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

Nealon answered 21/8, 2008 at 0:31 Comment(9)
So what does a statement do? Nothing?Policyholder
It can do something, but it doesn't evaluate to anything. Ie, you can not assign the result of it to a variable, whereas you can with an expression.Nealon
And therefor a statement must have side-effects, as my heavily down voted answer states. What other utility could a statement possibly have? Even if a NO-OP was considered to be a statement (it is only "statement" in grammar but not at the semantics layer because it is erased after parsing and semantics is what we are discussing here), it wouldn't explain what the heck the general utility of a statement is.Policyholder
@ShelbyMooreIII Statements do not need to do anything or have side effects. e.g., {} is a statement. Putting the word in scare quotes doesn't change that. Statements are syntactic constructs with semantics. There's no such thing as "the semantics layer" -- you seem to be referring to execution. You say you're trying to be accurate, but you've failed at that. Your complaint about " the ignorance of the down-voters" is pure ad hominem; you have no information about the mental states of the downvoters.Kodiak
Yeah, everyone is wrong except the intellectually dishonest. {} is defined to be a statement in the C# language spec.Kodiak
Beware in a language with bottom type. Some expression in that language doesn't evaluate into a value.Kigali
@ShelbyMooreIII assume there is a function a with definition function a() -> Bottom{ while(true){} }, then the type of expression a() is Bottom. This is valid even for an eagerly evaluated language like Rust. The semantics is that, if the expression is evaluated, the expression will not return a value, but instead abandons the current control flow. It can be an exception, or a call/cc, or as in example code, infinite loop.Kigali
Also, some piece of syntax doesn't evaluate to a value, like comment, declaration, etc. But they are not a statement.Kigali
@Akangka I'd think a declaration is a statement.Nealon
P
5

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
)
Pompano answered 19/12, 2008 at 1:36 Comment(0)
P
5

The de-facto basis of these concepts is:

Expressions: A syntactic category whose instance can be evaluated to a value.

Statement: A syntactic category whose instance may be involved with evaluations of an expression and the resulted value of the evaluation (if any) is not guaranteed available.

Besides to the very initial context for FORTRAN in the early decades, both definitions of expressions and statements in the accepted answer are obviously wrong:

  • Expressions can be unvaluated operands. Values are never produced from them.
    • Subexpressions in non-strict evaluations can be definitely unevaluated.
      • Most C-like languages have the so-called short-circuit evaluation rules to conditionally skip some subexpression evaluations not change the final result in spite of the side effects.
    • C and some C-like languages have the notion of unevaluated operand which may be even normatively defined in the language specification. Such constructs are used to avoid the evaluations definitely, so the remained context information (e.g. types or alignment requirements) can be statically distinguished without changing the behavior after the program translation.
      • For example, an expression used as the operand of the sizeof operator is never evaluated.
  • Statements have nothing to do with line constructs. They can do something more than expressions, depending on the language specifications.
    • Modern Fortran, as the direct descendant of the old FORTRAN, has concepts of executable statements and nonexecutable statements.
    • Similarly, C++ defines declarations as the top-level subcategory of a translation unit. A declaration in C++ is a statement. (This is not true in C.) There are also expression-statements like Fortran's executable statements.
    • To the interest of the comparison with expressions, only the "executable" statements matter. But you can't ignore the fact that statements are already generalized to be constructs forming the translation units in such imperative languages. So, as you can see, the definitions of the category vary a lot. The (probably) only remained common property preserved among these languages is that statements are expected to be interpreted in the lexical order (for most users, left-to-right and top-to-bottom).

(BTW, I want to add [citation needed] to that answer concerning materials about C because I can't recall whether DMR has such opinions. It seems not, otherwise there should be no reasons to preserve the functionality duplication in the design of C: notably, the comma operator vs. the statements.)

(The following rationale is not the direct response to the original question, but I feel it necessary to clarify something already answered here.)

Nevertheless, it is doubtful that we need a specific category of "statements" in general-purpose programming languages:

  • Statements are not guaranteed to have more semantic capabilities over expressions in usual designs.
    • Many languages have already successfully abandon the notion of statements to get clean, neat and consistent overall designs.
      • In such languages, expressions can do everything old-style statements can do: just drop the unused results when the expressions are evaluated, either by leaving the results explicitly unspecified (e.g. in RnRS Scheme), or having a special value (as a value of a unit type) not producible from normal expression evaluations.
      • The lexical order rules of evaluation of expressions can be replaced by explicit sequence control operator (e.g. begin in Scheme) or syntactic sugar of monadic structures.
      • The lexical order rules of other kinds of "statements" can be derived as syntactic extensions (using hygienic macros, for example) to get the similar syntactic functionality. (And it can actually do more.)
    • On the contrary, statements cannot have such conventional rules, because they don't compose on evaluation: there is just no such common notion of "substatement evaluation". (Even if any, I doubt there can be something much more than copy and paste from existed rules of evaluation of expressions.)
      • Typically, languages preserving statements will also have expressions to express computations, and there is a top-level subcategory of the statements preserved to expression evaluations for that subcategory. For example, C++ has the so-called expression-statement as the subcategory, and uses the discarded-value expression evaluation rules to specify the general cases of full-expression evaluations in such context. Some languages like C# chooses to refine the contexts to simplify the use cases, but it bloats the specification more.
  • For users of programming languages, the significance of statements may confuse them further.
    • The separation of rules of expressions and statements in the languages requires more effort to learn a language.
    • The naive lexical order interpretation hides the more important notion: expression evaluation. (This is probably most problematic over all.)
      • Even the evaluations of full expressions in statements are constraint with the lexical order, subexpressions are not (necessarily). Users should ultimately learn this besides any rules coupled to the statements. (Consider how to make a newbie get the point that ++i + ++i is meaningless in C.)
      • Some languages like Java and C# further constraints the order of evaluations of subexpressions to be permissive of ignorance of evaluation rules. It can be even more problematic.
        • This seems overspecified to users who have already learned the idea of expression evaluation. It also encourages the user community to follow the blurred mental model of the language design.
        • It bloats the language specification even more.
        • It is harmful to optimization by missing the expressiveness of nondeterminism on evaluations, before more complicated primitives are introduced.
      • A few languages like C++ (particularly, C++17) specify more subtle contexts of evaluation rules, as a compromise of the problems above.
        • It bloats the language specification a lot.
        • This goes totally against to simplicity to average users...

So why statements? Anyway, the history is already a mess. It seems most language designers do not take their choice carefully.

Worse, it even gives some type system enthusiasts (who are not familiar enough with the PL history) some misconceptions that type systems must have important things to do with the more essential designs of rules on the operational semantics.

Seriously, reasoning depending on types are not that bad in many cases, but particularly not constructive in this special one. Even experts can screw things up.

For example, someone emphasizes the well-typing nature as the central argument against the traditional treatment of undelimited continuations. Although the conclusion is somewhat reasonable and the insights about composed functions are OK (but still far too naive to the essense), this argument is not sound because it totally ignores the "side channel" approach in practice like _Noreturn any_of_returnable_types (in C11) to encode Falsum. And strictly speaking, an abstract machine with unpredictable state is not identical to "a crashed computer".

Pritchett answered 23/8, 2019 at 3:50 Comment(0)
G
3

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.

Giza answered 14/3, 2009 at 17:35 Comment(1)
A statement is not a special case of expression. In some languages (i.e. most C successors), it is actually the other way around.Kigali
A
3

Statements -> Instructions to follow sequentially
Expressions -> Evaluation that returns a value

Statements are basically like steps, or instructions in an algorithm, the result of the execution of a statement is the actualization of the instruction pointer (so-called in assembler)

Expressions do not imply and execution order at first sight, their purpose is to evaluate and return a value. In the imperative programming languages the evaluation of an expression has an order, but it is just because of the imperative model, but it is not their essence.

Examples of Statements:

for
goto
return
if

(all of them imply the advance of the line (statement) of execution to another line)

Example of expressions:

2+2

(it doesn't imply the idea of execution, but of the evaluation)

Abbasid answered 5/9, 2012 at 15:47 Comment(1)
@AustinHenley there is no requirement for that. In fact, an expression can definitely have a side effect.Kigali
D
2

Statement,

A statement is a procedural building-block from which all C# programs are constructed. A statement can declare a local variable or constant, call a method, create an object, or assign a value to a variable, property, or field.

A series of statements surrounded by curly braces form a block of code. A method body is one example of a code block.

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

Statements in C# often contain expressions. An expression in C# is a fragment of code containing a literal value, a simple name, or an operator and its operands.

Expression,

An expression is a fragment of code that can be evaluated to a single value, object, method, or namespace. The two simplest types of expressions are literals and simple names. A literal is a constant value that has no name.

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

Both i and s are simple names identifying local variables. When those variables are used in an expression, the value of the variable is retrieved and used for the expression.

Disjoint answered 17/9, 2012 at 12:11 Comment(1)
I'd rather write if(number >= 0) return true; else return false; or even better bool? IsPositive(int number) { if(number > 0) return true; else if(number < 0) return false; else return null;} :)Urbane
F
1

I prefer the meaning of statement in the formal logic sense of the word. It is one that changes the state of one or more of the variables in the computation, enabling a true or false statement to be made about their value(s).

I guess there will always be confusion in the computing world and science in general when new terminology or words are introduced, existing words are 'repurposed' or users are ignorant of the existing, established or 'proper' terminology for what they are describing

Feuchtwanger answered 7/5, 2013 at 15:18 Comment(0)
G
1

Here is the summery of one of the simplest answer I found.

originally Answered by Anders Kaseorg

A statement is a complete line of code that performs some action, while an expression is any section of the code that evaluates to a value.

Expressions can be combined “horizontally” into larger expressions using operators, while statements can only be combined “vertically” by writing one after another, or with block constructs.

Every expression can be used as a statement (whose effect is to evaluate the expression and ignore the resulting value), but most statements cannot be used as expressions.

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

Gallic answered 8/9, 2014 at 10:46 Comment(0)
L
0

Statements are grammatically complete sentences. Expressions are not. For example

x = 5

reads as "x gets 5." This is a complete sentence. The code

(x + 5)/9.0

reads, "x plus 5 all divided by 9.0." This is not a complete sentence. The statement

while k < 10: 
    print k
    k += 1

is a complete sentence. Notice that the loop header is not; "while k < 10," is a subordinating clause.

Lunate answered 26/3, 2011 at 1:40 Comment(5)
while is an expression is some languages such as Scala. You are conflating grammar with typing. See my answer.Policyholder
Here is the while loop in scala: tutorialspoint.com/scala/scala_while_loop.htm The loop with its predicate and no body is not a grammatically complete sentence. It is not a full expression. You need the body to complete it as an expression.Lunate
A while with a body is still an expression in Scala. It may also be a statement if it creates side-effects, which what my heavily downvoted answer allows (an expression can also be a statement). My answer is the only correct one. Sorry to all those readers who can't understand.Policyholder
What do you mean by grammatically complete? In C, (x + 5)/9.0 can definitely stand alone as an statement. Also, If by grammatically complete, you mean a valid program, C does not allow statements to stand alone as a single program.Kigali
Grammatically complete: constitutes a complete sentence.Lunate
K
0

In a statement-oriented programming language, a code block is defined as a list of statements. In other words, a statement is a piece of syntax that you can put inside a code block without causing a syntax error.

Wikipedia defines the word statement similarly

In computer programming, a statement is a syntactic unit of an imperative programming language that expresses some action to be carried out. A program written in such a language is formed by a sequence of one or more statements

Notice the latter statement. (although "a program" in this case is technically wrong because both C and Java reject a program that consists of nothing of statements.)

Wikipedia defines the word expression as

An expression in a programming language is a syntactic entity that may be evaluated to determine its value

This is, however, false, because in Kotlin, throw new Exception("") is an expression but when evaluated, it simply throws an exception, never returning any value.

In a statically typed programming language, every expression has a type. This definition, however, doesn't work in a dynamically typed programming language.

Personally, I define an expression as a piece of syntax that can be composed with an operator or function calls to yield a bigger expression. This is actually similar to the explanation of expression by Wikipedia:

It is a combination of one or more constants, variables, functions, and operators that the programming language interprets (according to its particular rules of precedence and of association) and computes to produce ("to return", in a stateful environment) another value

But, the problem is in C programming language, given a function executeSomething like this:

void executeSomething(void){
    return;
}

Is executeSomething() an expression or is it a statement? According to my definition, it is a statement because as defined in Microsoft's C reference grammar,

You cannot use the (nonexistent) value of an expression that has type void in any way, nor can you convert a void expression (by implicit or explicit conversion) to any type except void

But the same page clearly indicates that such syntax is an expression.

Kigali answered 11/6, 2020 at 12:9 Comment(0)
I
0

A statement is a block of code that doesn't return anything and which is just a standalone unit of execution. For example-

if(a>=0)
printf("Hello Humen,I'm a statement");

An expression, on the other hand, returns or evaluates a new value. For example -

 if(a>=0)
    return a+10;//This is an expression because it evalutes an new value;

or

 a=10+y;//This is also an expression because it returns a new value. 
Ingest answered 12/8, 2020 at 14:8 Comment(0)
V
0

Expression

A piece of syntax which can be evaluated to some value. In other words, an expression is an accumulation of expression elements like literals, names, attribute access, operators or function calls which all return a value. In contrast to many other languages, not all language constructs are expressions. There are also statements which cannot be used as expressions, such as while. Assignments are also statements, not expressions.

Statement

A statement is part of a suite (a “block” of code). A statement is either an expression or one of several constructs with a keyword, such as if, while or for.

Volney answered 20/8, 2020 at 10:58 Comment(0)
P
-7

To improve on and validate my prior answer, definitions of programming language terms should be explained from computer science type theory when applicable.

An expression has a type other than the Bottom type, i.e. it has a value. A statement has the Unit or Bottom type.

From this it follows that a statement can only have any effect in a program when it creates a side-effect, because it either can not return a value or it only returns the value of the Unit type which is either nonassignable (in some languages such a C's void) or (such as in Scala) can be stored for a delayed evaluation of the statement.

Obviously a @pragma or a /*comment*/ have no type and thus are differentiated from statements. Thus the only type of statement that would have no side-effects would be a non-operation. Non-operation is only useful as a placeholder for future side-effects. Any other action due to a statement would be a side-effect. Again a compiler hint, e.g. @pragma, is not a statement because it has no type.

Policyholder answered 17/8, 2015 at 18:25 Comment(1)
The distinction has nothing to do with the type of expressions. Syntactically defined statements have no types at all in many languages. Although I'm not against to assign a type on such terms in theory, different treatments on @pragma or /*comment*/ are logically inconsistent.Pritchett
P
-13

Most precisely, a statement must have a "side-effect" (i.e. be imperative) and an expression must have a value type (i.e. not the bottom type).

The type of a statement is the unit type, but due to Halting theorem unit is fiction so lets say the bottom type.


Void is not precisely the bottom type (it isn't the subtype of all possible types). It exists in languages that don't have a completely sound type system. That may sound like a snobbish statement, but completeness such as variance annotations are critical to writing extensible software.

Let's see what Wikipedia has to say on this matter.

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

In computer programming a statement is the smallest standalone element of an imperative programming language that expresses some action to be carried out.

Many languages (e.g. C) make a distinction between statements and definitions, with a statement only containing executable code and a definition declaring an identifier, while an expression evaluates to a value only.

Policyholder answered 9/12, 2011 at 19:4 Comment(21)
Please don't redefine general technical terms 'expression' and 'statement'. My comments and answer are correct for C#. If f(); has the type void and has no side-effects, then it is a NOOP. A good compiler will not allow NOOPs. If f(); has no side-effects and its return value is not used, it is also a NOOP. I did answer the question w.r.t. C#. I answered with one precise sentence. That sentence is correct for C#. I then elaborated about what void in C# means in terms of type theory. Type theory applies to C#.Policyholder
See my comments under Mark Cidade's answer, which explain why a statement is often in reality the bottom type and not the unit type. To say that a statement "does something" is incredibly imprecise, as an expression also "does something"-- it evaluates to a value. I know what people are trying to say, they just don't choose precise words and definitions. The precise word is (a statement must not be) referentially transparent (i.e. imperative). That is more precise than "does something" or "side-effect".Policyholder
A statement need not have a side effect. For instance, in python pass is a statement. It is a no-op, and it does not evaluate to anything.Nealon
@MatthewSchinckel If it doesn't have a side-effect, then it is either an expression or a NOOP. A NOOP does nothing, so it can be removed from the program. It is a simple process of logical elimination. If you don't define statement as requiring a side-effect, then statement is same as expression. What other attribute would you use to differentiate a statement from an expression?Policyholder
-1 This is wrong. A statement doesn't have to have a side-effect. See section 1.5 of the C# Language Specification. Not only it doesn't specify that statements must have side-effects, but it also lists several statements that can have no side-effects.Fillander
@Fillander I read that section. Declaration, Expression, Selection, Iteration, and Jump statements may all create side-effects. But if there is an RT expression, then it is not a statement. I realize the specification is equating expressions with statements, but this question asked for the difference between them. So either the question has no answer, or you are taking the C# spec too literally. The top voted answer is trying to say what I did. But "does something" is meaningless. "side-effect" is the meaningful way to say "does something". We have to think, not just regurgitate.Policyholder
@ShelbyMooreIII You are right. The official documentation is wrong. Marc Gravell and Jon Skeet, who are possibly the most respect C# posters active on SO outside of Eric Lippert, are wrong. I, and all the others who downvoted you and left comments explaining our position are wrong. You are right. You clearly are the only person who knows what they are talking about, since you are so much smarter than all of the rest of SO.Fillander
@Fillander They are very much correct about the way most C# users want to understand concepts. But I am showing them a big picture view, pehaps they hadn't been exposed to. I understand cognitive dissonance, I suffer it too. I made similar more narrow assumptions in the past. I used to come from the C/C++/C# world, so I know how hard it was for me to adjust to Haskell, Scala, and more general concepts. But I am willing to accept that my answers are not as helpful as others in this context. So let's say you are correct in a sensePolicyholder
Knowing the precise definition of concepts like statement, expression, cast, conversion etc. has zero impact on 99.999% of everyday programming tasks. Think about that. Also: most people don't care about Haskell and Scala.Fillander
@Fillander But if I may, plz think about this. If expression is distinct from statement, what is the distinct attribute? "Does something"? Define "something". I think you will find that my answer is the same as the top voted answer. I just defined what "something" is. The C# spec is just being literal as a convenience. It is not expecting that you think expressions are not distinct from statements. Or you believe that expressions are just a subset of statements, but that doesn't work. Should I show how that can't work?Policyholder
@ShelbyMooreIII I never claimed that expressions are just a subset of statements. But again, that's irrelevant.Fillander
@Fillander Indeed Haskell is obtuse and due to lazy evaluation has space and time indeterminism, which makes it very hard to debug. Also it doesn't have virtual inheritance. Scala fixes many of these things and is the fastest growing language right now, but still very tiny adoption. Scala is pretty good, but its syntax has too many variants, e.g. 9 ways to write a function, and other issues. Also tied to Java libraries for most part for now. Does C# run on Android? Ok good that you don't think expressions are subset of statements. What does "does something" mean? What is "something"?Policyholder
let us continue this discussion in chatFillander
@Fillander I respect those guys. I could never answer all the questions they do. Their knowledge is much broader than mine. They are really deep and current in with coding on those platforms. They probably have a lot more energy than me too. And they are probably just as smart if not smarter than me. I want it to be clear that it is not an issue of respect. I just want people to be open-minded and give time to things out. Sometimes things are not what they seem to be.Policyholder
The C# language specification does not require that statements have side-effects. Empty statements are legal (section 8.3), whether the compiler leaves them in or not. In fact, since dealing with no-op statements is left up to the implementation, even NOOPs can potentially affect the compiled code and the program's performance. So your answer is both academically and practically wrong.Ploughman
Whether NOOPs get compiled or not is irrelevant anyway. { return 5; } is a statement that does not produce side-effects, unless you were to redefine "side-effect" to include returning a single value. Not only is this not the accepted meaning (even in Haskell), it's only meaningful in a completely academic sense. () => 5 and () => { return 5; } have the same result once evaluated, but one is an expression and the other is not.Ploughman
@JustinMorgan at the abstract level of language design a return is either just an expression that is the value of the enclosing function or it is both that and a short-cut for writing a more complex if-else structure so that all code paths resolve to a value. That non-functional languages get this wrong is not surprising. For example, in Scala the return may be omitted and you may just write 5 at the end of the code path for the function.Policyholder
@MatthewSchinckel A pass statement most definitely has side-effects. It causes the interpreter to expend CPU cycles to bypass it. It is also intended as placeholder for a function that will add side-effects in place of the pass statement thus it is way of indicating future side-effects.Policyholder
Usual type systems cannot handle side effects in the metalanguage (during the translation phases) well. The void type renders a program semantically invalid and normally requires diagnostics from the implementation when such a term is evaluated in a context needs a (non-void) value, this is essentially an action executed by the translator. It has nothing to do with the side effects mentioned here for the object language. It is true that the concept of statements is just not so useful, but this is not the reason to change the well-known meaning of it.Pritchett
"It causes the interpreter to expend CPU cycles to bypass it" [citation needed]. Do you have any disassembled python bytecode as a proof?Kigali
@Akangka this will be censored as usual, but my 2015 statement what not about a bytecode interpreter, instead I referring to a source code interpreter. If it’s entirely erased in bytecode then it’s equivalent to a comment w.r.t. side-effects vs. values and thus irrelevant to my definitional points. Now shoo.Policyholder

© 2022 - 2024 — McMap. All rights reserved.