0

I am reading "Scala Programming" book of Odersky, and he mentions how if expressions in Scala are different because they return values, but from my experience the same can happen if statements in imperative languages such as Java? So what makes the if expressions different from Java's if statements?

  • Java isn't imperative, it's an object oriented language. – akuzminykh Jun 04 '20 at 18:37
  • 4
    You can't do this in **Java** for example: `val foo = if (bar) 3 else 5`, so i am not sure what was your experience with **Java** or if you misunderstand the term _"return a value"_. - Also, **Scala's** `if` is an _expression_ (because it computer / returns a value) **Java's** `if` is an _statement_ (because it just manipulates the control flow) – Luis Miguel Mejía Suárez Jun 04 '20 at 18:37
  • 8
    @akuzminykh being OOP doesn't remove the fact that it is imperative too. – Luis Miguel Mejía Suárez Jun 04 '20 at 18:38
  • @LuisMiguelMejíaSuárez You can do this `val foo = bar ? 3 : 5` in Java. `if` is not syntactically present but it is here. – Soleil Jun 04 '20 at 20:06
  • 1
    @Soleil-MathieuPrévot that is not an `if` that is the _trinary operator_ which is an expression. And it exists precisely because an `if` is not an expression; and this is a common use case, to avoid an unnecessary non-final variable. – Luis Miguel Mejía Suárez Jun 04 '20 at 20:08

5 Answers5

6

You are talking about different things.

When you say that if statements can return values, you're thinking of having return statements in the body:

if (true) {
  return 1;
} else {
  return 2;
}

When Odersky says that the Scala if expression returns a value, it means that you can use the if expression itself as a value:

var x = if (true) { 1; } else { 2; }

It is therefore similar to the trinary operator true ? 1 : 2 in Java.

In other words, where Java has a whole new way to write conditional statements that need to be read and nested differently, Scala just lets you use the same if expression for both. Letting if return a value instead of being a value-less statement is what allows this.

that other guy
  • 116,971
  • 11
  • 170
  • 194
3

You can write in Java:

val foo = bar ? 3 : 5

if is not syntactically present but it is here semantically.

Soleil
  • 6,404
  • 5
  • 41
  • 61
1

Short explanation

In java:

if (foo) {
    return 5;
} else {
   return 3;
}

In scala:

return if (foo) 5 else 3;

-- that's what Odersky is talking about.

Longer explanation

Different meanings of the word 'return'.

A method (java's name for a function, really) can return a value; you use the return keyword to do it.

An expression has a value. One could say that an expression returns that value.

That's the two different meanings of the word.

For example, the expression 5 + 2, legal in both scala and java, resolves to the value 7. You could say that it 'returns' this.

In java, if constructs are statements (meaning: things that do not have a value). In scala, if is an expression - it does have a value. This is valid scala:

var x = if (foo) 5 else 3;

The constructor if (foo) 5 else 3; can be said to return an int value (and it'll return 5 or 3 depending on foo).

In java that kind of construct isn't legal.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • 2
    Method is not not a Java name for a function. A method and a function are two different things. – Luis Miguel Mejía Suárez Jun 04 '20 at 18:53
  • Now you're just splitting hairs on precise definitions. 'Method' in general programming parlance overlaps in meaning with 'Function' so much as to be nearly identical (Method adds some extra meaning on top of the more generic notion of 'function'). There's no Universal Programmers Specification with Precise Meaning of All Jargon That Shall Ever Be Used, stop acting like this exists. – rzwitserloot Jun 04 '20 at 22:06
  • 2
    On both **Java** and **Scala** _Method_ and _Function_ are two different terms, with different meanings. So, at least in this context, the comment is ok. Also, I am not _splitting hairs_, the difference is important [at least in Scala](https://stackoverflow.com/questions/2529184/difference-between-method-and-function-in-scala). – Luis Miguel Mejía Suárez Jun 04 '20 at 22:16
1

Scala's if expression is an expression, which means it evaluates to a value, so we can assign it to a variable or pass it in as an argument to a method

val x = if (true) 1 else 2  // ok
f(if (true) 1 else 2)       // ok

Java's if statement is a statement, which means it executes a side-effect, so we cannot assign it to a variable or pass it as an argument to a method

Integer x = if (true) return 1; else return 2;   // error
f(if (true) return 1; else return 2;)            // error

Instead in Java we have to do something like

Integer x;
if (true) 
  x = 1; 
else 
  x = 2;

Note how if statement is executed for the side-effect of assigning a value to x variable.

Mario Galic
  • 47,285
  • 6
  • 56
  • 98
  • Quick addition: as stated by @Soleil, java has the ternary (`SomeObject obj = ? : ;`). Also, if java would add an if expression, just like there now is a switch expression, you'd probably would have to use the `yield` keyword rather than the `return` keyword similar to how it is used in switch expressions, since `return` is only used to return from methods, not to yield values from expressions. – Rik Schaaf Jul 20 '23 at 15:01
0

In Java, blocks don't return values, only methods (lambda expressions too, but they basically get turned into methods).

However, in Scala, you can treat a block as an expression, like this:

val x: Int = {
  // very complex computations here
  val arr: Array[Int] = ???
  arr(0) // returns the first element
}

This would have to be written in Java as the following (assuming you want to keep the variable names used for those "complex computations" hidden), but you lose the ability to declare x final.

int x;
{
  //very complex computations here
  int[] arr = ...
  x = arr[0];
}

These two are very different.

In fact, in Scala, methods are written in the form def foo: T = {...} where the returned value is a block that is treated as an expression of type T.

An example with if-statements:

Scala:

val x = if (cond) {
  val temp = ???
  impureMethod(temp)
  temp
} else 0

In Java:

int x;
if (cond) {
  var temp = ...;
  impureMethod(temp);
  x = temp;
} else x = 0;

Again, in the Java example, you lose the ability to use final.

However, you can use the conditional operator in Java if it's something simple, e.g. if (cond) x else y (Scala) is pretty much the same as cond ? x : y in Java.

user
  • 7,435
  • 3
  • 14
  • 44