What makes a construct an expression rather than a statement, and why can only one of them nest inside another?
answer
- two kinds of code shapes
- one leaves a value behind
- the other is run for effect
- value-denoting forms can nest
- statements can only be sequenced
basics
~20 sAn expression evaluates to a value, so it can sit anywhere a value is expected and nest inside a larger expression. A statement is run for its effect and denotes nothing, so nothing can be built around it.
solid answer
~50 sAn **expression** denotes a value: evaluate it and you are left with something the surrounding code can pass, bind, return or feed into a bigger expression. A **statement** is executed for its effect — it changes state or moves control — and leaves nothing behind, so an enclosing form has nothing to consume. That is why nesting, not syntax, is the real dividing line. In a grading routine, `record(band(normalise(raw)))` composes because every call denotes a value and can be dropped into the slot where a value is expected; a branch that merely assigns into a variable can only be *sequenced* before or after other statements. Languages differ in how much of their syntax denotes values — some treat a conditional or a whole block as value-denoting, others do not — but the property itself is always the same question: does this form leave a value behind?
code
pseudocode · 11 lines// statement form: the branch only performs an effect
set band to nothing
if score >= 90 then
set band to "A"
else
set band to "B"
end
report(band)
// expression form: the branch denotes a value
report( if score >= 90 then "A" else "B" )go deeper
Be able to state it in one line — an expression evaluates to a value, a statement is run for its effect — and give one concrete example of each from code you have actually written.
Go one step past the definition to the consequence: a value-denoting form can be nested, bound and returned, so it composes, while a statement can only take a position in a sequence.
Show where the distinction changed a review decision: branches that existed only to write into a variable declared above them, and what the surrounding routine looked like after the choice denoted a value.
Judge how far to push expression-orientation in a house style, given that some constructs in your stack simply are statements and forcing every one of them into a value costs more readability than it buys.
## Two kinds of code, separated by one property Every construct you write exists for one of two reasons. Either it **denotes a value** — evaluate it and what remains is something the surrounding code can use — or it is **executed for its effect**: it writes to a variable, transfers control, or touches the outside world, and leaves nothing behind that anything could consume. The first kind is an **expression**. The second is a **statement**. The property is not about length, punctuation or how clever the code looks. A ten-line arithmetic formula is an expression; a one-word jump out of a routine is a statement. The test is always the same: *after this runs, is there a value here?* If yes, the construct can be used as a part of something bigger. If no, it can only take its turn in a sequence. ## Why nesting is the real test Composition means putting a whole where a part is expected. An expression can appear in every one of those slots: - as an argument in a call; - as the right-hand side of a binding; - as the value a function hands back; - as an element inside a collection literal; - as an operand of another expression. A statement has exactly one legal position: the next slot in a sequence of statements. You cannot pass it, you cannot bind it to a name, and you cannot put it inside anything. That single restriction is the whole practical consequence of the distinction, and it is what an interviewer is listening for. A candidate who recites the two definitions has said the floor; a candidate who says "so the expression form can be nested and the statement form can only be sequenced" has answered the question. ## A grading rubric, in both shapes Consider a routine that turns a numeric score into a band. ```pseudocode // statement shape: the branch is run for its effect set band to nothing if score >= 90 then set band to "distinction" else set band to "pass" end record(band) // expression shape: the branch denotes a value record( if score >= 90 then "distinction" else "pass" ) ``` Both run the same test and record the same string. What differs is where the choice can live. In the first shape the branch produces nothing, so a name has to be created *in advance* for the branches to write into, and the call has to come after them. In the second the choice itself denotes a string, so it can be handed straight to the call — no name, no ordering constraint between the branch and the use. ## What follows from the difference | property | expression | statement | |---|---|---| | what it leaves behind | a value | nothing | | can nest inside another form | yes | no | | can be bound to a name directly | yes | no | | can be handed to a call | yes | no | | needs a place prepared for its result | no | yes, when it writes one | | composes into larger units | yes | only by sequencing | The row that pays for the rest is the last one. Because expressions compose, an expression-shaped routine can be read inside-out: you understand the innermost part, then the part that wraps it, and you never have to remember what happened earlier. A statement-shaped routine has to be read in order, carrying the current value of every name in your head, because any earlier statement may have changed one. ## Where the line actually sits Do not carry one language's line into an interview as if it were universal. Languages differ in how far the expression side reaches: some treat the two-way choice, the multi-way choice and even a block as value-denoting forms; others treat all three as statements and offer a separate small operator for the two-way case only; some treat assignment itself as denoting a value, which is a genuinely different design with its own hazards. What is *not* language-specific is the underlying question, and it is the one to answer at a whiteboard: does this form denote a value, or is it run for what it does? One more clarification that comes up constantly. The same syntax can appear on both sides of the line. A call that hands back a value is an expression; the very same call written on its own line, with the result ignored, is being used as a statement. The role, not the spelling, decides. ## The trap The trap is treating this as trivia. It is the root of the next question in the chain — why a routine has a variable declared empty at the top and assigned in every branch below — and that variable is the thing interviewers are actually hunting for. It exists only because the branch produced nothing to bind.
- Is a call an expression or a statement?Either, depending on the role it is playing. A call that denotes a value and is used for that value is an expression; the same call written on its own line with its result ignored is being used as a statement. The syntax does not decide it — whether the surrounding code consumes a value does.
- Why can a value-denoting conditional be passed straight to a call while a branching statement cannot?A call needs a value in each argument slot. The value-denoting conditional evaluates to one, so it fits the slot directly. The branching statement evaluates to nothing, so there is nothing to put in the slot; the only way to get its result into the call is to prepare a name first, have the branches write into it, and pass the name.
- Does the distinction still matter in a language where almost everything denotes a value?Yes, and it shifts to a sharper question. When nearly every form denotes a value, the interesting thing about a form is no longer whether it can nest but what it also does while nesting. A construct that yields a value and writes to state can be dropped into an expression, and the write travels with it.
An expression is a number written on a slip you can hand to someone, who can add it into a larger total. A statement is flipping a switch: the room changes, but you have nothing in your hand to pass on.
saying these in an interview costs you the question
- Says an expression is just a statement without the terminator.
- Says every statement secretly returns a value that is discarded.
- Thinks any short one-line construct counts as an expression.
- Treats the distinction as syntax trivia with no consequence.
- Assumes every language draws the line in the same place.