1

Why do we have the distinction between statements and expressions in most programming languages?

For example, in Java, assuming f and g return ints, this still won't compile because it's a statement and statements don't return values.

// won't compile
int i = if (pred) { 
    f(x); 
} else {
    g(x);
}

but in Scala, it's very happy with treating if as an expression.

// compiles fine
val i: Int = if (pred) f(x) else g(x)

So if there's no problem treating an if statement as an expression, why was there a distinction in the first place?

gnat
  • 21,442
  • 29
  • 112
  • 288
cdmckay
  • 119
  • 3

2 Answers2

0

The if could return a value here because both of the functions also return values. But there are void functions as well, and f and g might have different return types, which would make it unclear what the type of this if would be. In effect, if you ban statements from a programming language, you also ban void methods, strict typing and some more common constructs that a lot of people don't want to see go.

(And yes, I am aware that other people would be very glad to see them go and will tell me and you and everyone at great length and high volume how glad they would be - this is a Holy war, please don't fuel it.)

Kilian Foth
  • 107,706
  • 45
  • 295
  • 310
  • 1
    Why are you banning strict typing? – Tobias Brandt Aug 22 '14 at 07:36
  • 1
    An `if` whose branches return different types is simply illegal in such a language. `void` methods don't exist, instead the unit type `()` is used which *has* a value (only a single, and hence meaningless, one) to be returned. And unless you pursue purely functional programming (in which case none of your concerns even arise), you will have a operator to "ignore" a value, i.e. execute an expression for side effects and then return `()`. Armed with that, you can trivially write `if (c) { f(); } else { g(); }` where `f` and `g` return different types and `;` is the execute-and-ignore operator. –  Aug 22 '14 at 08:31
  • If `f` and `g` have different types, then the type of the `if` expression will be the most derived common supertype. Easy. – Jörg W Mittag Aug 22 '14 at 21:06
0

Because it is confusing, therefore it is easier to introduce bugs.

One of the most famous in C is: if (a = b) instead of if (a == b). With a distinction between expressions and statements, the compiler would have complained.

Going on with C, there is a specific form of if whenever it should return a value:

pred ? f(x) : g(x)
mouviciel
  • 15,473
  • 1
  • 37
  • 64
  • 1
    A distinction between expressions and statements doesn't necessarily help with `if (a = b)`, as long as assignment is an expression (it's one in Java and C# which address this problem through other means). Making assignment a statement would help, but equally well one can restrict `if` to boolean values (Java, C#) and in a expression-oriented language, additionally make it the moral equivalent of a "statement": An expression that returns the unit type `()`, which is what Rust does. –  Aug 22 '14 at 08:24
  • 1
    @delnan - You are correct. In my mind an assignement is a statement, not an expression, i.e., _let `a` take the current value of `b`_, without the second part: _and return that value_. – mouviciel Aug 22 '14 at 08:56