What is the difference between an expression and a statement?
Asked Answered
B

3

10

I know that this might be a duplicate, but I have not found sufficient answers to my examples. In general, what is the difference between statements and expressions? This is a distinction which I have not fully distinguished yet. I know that typically an expressions is supposedly anything that returns a value, such as a literal, or a function. Statements are usually said to be commands to the interpreter, such as "print such and such" or "do . . . while". However, I don't get it.

Wouldn't it make sense to say that print is an expression, since it is a function printing an input (input to output)? Also, people usually say that x = 1 is a statement, but couldn't this be considered an expression where the assignment operator is a function acting on two inputs and the output is that x refers to 1? Finally, couldn't a flow control structure such as if . . . else be considered a three-argument function in which one of the other arguments are returned based upon the truth value of the first input, making it an expression?

I am probably confused because I have a background in LISP, where everything is an expression. It seems that I can't shy away from the thought that most programming constructs are expressions at their core. Thus, could someone explain what really is the difference between a so-called statement and an expression?

Bitartrate answered 2/9, 2015 at 2:18 Comment(2)
The answer is more philosophical than practical. Statements typically have side effects, whereas expressions are generally more algebraic in nature. In purely functional languages, there are no statements. That is to say that even those things which execute side effects (to a file, for instance) are expressed in terms of values which represent (ideally) all mutations - including failures. Imperative languages utilize statements to execute arbitrary code, such as assigning a value to a variable, or printing to the console, and potentially communicate failures though exception propagation.Ermeena
The distinction depends on what language you're talking about. In C, x = 1 is an expression and x = 1; is a statement. In Ada, x := 1 is not an expression, but x := 1; is a statement.Fizzy
D
11

The definition of expression and statement - and even if there is such a thing as one or the other - is specific to a particular language and the grammar that describes it.

Well, let's go:

  • A statement is some 'evaluatable code'1 that does not appear in an expression context; and

  • An expression is code that appears in a context where the resulting value can be consumed through substitution of the expression.

{A very loose 'definition', but there is no One Language. While some languages are strict about when side-effects can and cannot occur - and code that executes without result or side-effect is useless - I do not believe discussing such is fundamental to the differences.}

For instance, let's look at printf in C. This is a function that side a side-effect and it returns a value; usually the return value is ignored. Thus printf can appear as both a statement

printf("Hello world!");

and an expression

if (8 == printf("Hello %s!", name)) { // ..

(A function call with a return type of void can only appear in a statement context in C but this is imposed by the type system and not the parser.)

Likewise, take these two lines in JavaScript x = 1; and x = (y = 2);. x = .. is a statement while y = 2 is an expression that yielded a value.

In both of these examples we see that it is the grammar production that determined if it is treated as statement or an expression.

In contrast Ruby can treat the 'top level' assignment as an expression:

[1].map {|x| x = 2}

Now let's take a peak a Python (2.x). In this case print is a statement which is why these work and don't work, respectively:

print "Look ma, no parenthesis!"
x = lambda y: print "Whoops!"       # invalid, print not an expression

And what about at if constructs - are these statements or expressions? Again, it depends on the particular language. In C and Java such are clearly statements: there is no way to use such as a substitute for a value.

On the other hand, Scala (and Ruby) allows such flow control constructs to be used as expressions, although they can also appear as statements:

var emotionalResponse = if (color == "green") {
                          log.cheer()
                          new Cheering()
                        } else {
                          new Tears()
                        }

Whew. That is a lot - and it's not nearly comprehensive. But, back to the 'definition' which can be restated about as so, when taking the various examples above into account:

If the construct in question can occur where a value is required (eg. on the right-hand-side of an assignment, as a function argument, as input to another expression) then it can be treated as an expression; and most definitely is an expression when in such a context. If the construct appears in a location where the value cannot be accessed through substitution then it is (or rather, can act as) a statement.


1 Another class of productions to condition is declarations, such as a function declarations in C or class definitions in Java, and are arguably not statements; since the following is already so fragmented this is as much of a note that gets.

Dagney answered 2/9, 2015 at 2:45 Comment(3)
printf() isn't a statement. The function call is the statement: printf() is merely the function that is called.Graver
@EJP "is a function .. can appear as" - although I am open to more clear proposals.Dagney
@EJP: In C, printf("Hello") is an expression, not a statement. printf("Hello"); is a statement. An expression statement is a particular kind of statement, consisting of an (optional) expression followed by a semicolon. (The null statement is treated as an expression statement for some reason.)Fizzy
R
4

An expression yields a value, a statement does something.

eg; in C return a+5; is a statement, it exits a function giving the value derived from the expression a+5 to to the caller.

whether print is an expression or a statement depends on the language.

BASIC has print which is not function-like it's something that's handled as a special case by the sompiler. similarly pascal has write and writeln which are also special cases, not function calle, on the other hand C has puts() and printf() which are both functions. and allows the programmer to write similar functions that work in the same way.

Recondition answered 2/9, 2015 at 2:23 Comment(3)
An expression can 'do something'.Dagney
@Dagney perhaps a distinction between an expression with side-effects and one without is warranted then.Scraper
@Scraper I don't think one needs to discuss side-effects of expressions to answer the question (although it does fit it in well); the difference between a statement and an expression is a grammar production rule.Dagney
E
2

The answer is more philosophical than practical. Statements typically have side effects, whereas expressions are generally more algebraic in nature.

In purely functional languages, there are no statements. That is to say that even those things which execute side effects (to a file, for instance) are expressed in terms of values which represent (ideally) all mutations - including failures.

Imperative languages utilize statements to execute arbitrary code, such as assigning a value to a variable, or printing to the console, and potentially communicate failures though exception propagation.

Purely functional expressions merely reduce the cognitive overhead of dealing with mutations by exposing those mutations as values in-and-of-themselves. Mix this with pattern matching, and you are forced to explicitly handle all success and failure scenarios and consequently turn them in to values, explicitly mapping or filtering any failures.

Imperative statements are not required to expose failures as values, and therefore there is always the possibility of arbitrary code existing in an unsuspecting method in such a way that it is easily overlooked. Statements, such as method invocations or variable assignments (x = y = z()), can generally fit the mold of an expression while still executing arbitrary code and failing to communicate failures as values.

In the end, you cannot avoid mutation. You can, however, make it more explicit. This means statements and expressions differ mainly in a philosophical manner, both existing to answer the same question - how should we expose mutations within the context of code execution?

Ermeena answered 14/11, 2017 at 17:59 Comment(1)
This should be accepted answer. Thank you. Good catch!Rossini

© 2022 - 2024 — McMap. All rights reserved.