In lots (actually all I've ever used) of functional languages there is no distinction between a statement and an expression and the last value of each code block is the "return value" of the block. On the other hand languages not generally considered purely functional usually introduce this distinction.
As an example of what I'm talking about, the following python code prints None
:
def foo():
5 + 5
print(foo())
while the scheme code prints 10
(define (foo) (+ 5 5))
(display (foo))
Obviously I'm not interested in subjective answers of people who prefer one style to the other, but objective reasons.
To me it seems the distinction makes the grammar and implementation of the language more complicated (one less obvious example of this being the necessary exceptions in the c++ standard for templates and void types, or the introduction of "shortcut if statements", like ?
in c-influenced languages) without a real benefit - but most likely there's a reason why even new, modern languages still have this distinction.
Ubiquitous side effects.
If you are in a purely functional language, everything is an expression. Even "statements" which return something like ()
(possibly distinguished by their type, e.g. IO ()
.
However, the majority of programming languages by default permit effects anywhere or everywhere, so sequencing becomes key, and thus you bake in special syntax for ordering statements to the computer, often separated with semicolons.
This isn't the case for pure expressions, which can be evaluated in any order that preserves the expression semantics.
Side effecting actions are considered such special expressions that they get special syntax.
First, let me say that I think you're asking two, maybe more, different questions: "Why are some expressions distinguished syntactically from others?" and "Why are the semantics for sequencing what they are?"
For your first question: The sense I get from the many things I've read is that statements are expressions, but a restricted class of expressions that cannot appear as subexpressions in all circumstances, e.g.,
x = 4
y = (x += 1)
The above python code will generate a syntax error because a statement appeared in a place where an (unrestricted) expression was expected. I associate statements with side-effects, with sequencing, and with the imperative style. I don't know if you consider programming style a subjective answer to your question (style itself certainly is subjective).
I'm very interested to hear others' takes on this question, too.
For the second question: Semantics are sometimes arbitrarily decided, but the aim is a reasonable semantics, with different language designers simply differing on what is most reasonable (or most expected). It surprised me to learn that if control reaches the end of a function body in Python, it returns None, but those are the semantics. Designers have to answer similar semantics questions like "What should the type of a while loop be?" and "What should the type of an if statement be if it doesn't have an else branch? and Where should such statements be allowed syntactically (issues can arise if such an if statement is the last statement in a sequence of statements)?"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With