I am confused.
I thought everything is expression because the statement returns a value. But I also heard that everything is an object in scala.
What is it
Is everything a function or expression or object in scala?
None of it.
There are things that are not objects. e.g. classes, methods.
There are things that are not expressions. e.g. class Foo { }
is a statement, and does not evaluate to any value. (This is basically the same point as above.)
There are things that are not functions. I don't need to mention any examples for this one as there would be plenty in sight in any Scala code.
In other words, "Everything is a X" is nothing more than a sales pitch (in case of Scala).
The distinction here is that the assertion "everything is a expression" is being made about blocks of code, whereas "everything is an object" is being made about the values in your program.
In the Java language, there are both expressions and statements. That is, any "block" of code is either an expression or a statement;
//the if-else-block is a statement whilst (x == 4) is an expression
if (x == 4) {
foo();
}
else {
bar();
}
Expressions have a type; statements do not; statements are invoked purely for their side-effects.
In scala, every block of code is an expression; that is, it has a type:
if (x == 4) foo else bar //has the type lub of foo and bar
This is extremely important! I cannot stress this enough; it's one of the things which makes scala a pleasure to work with because I can assign a value to an expression.
val x = if (x == 4) foo else bar
By value, I mean something that we might reference in the program:
int i = foo(); //i is a reference to a value
java.util.TimeUnit.SECONDS;
In Java, the i
above is not an object - it is a primitive. Furthermore I can access the field SECONDS
of TimeUnit
, but TimeUnit
is not an object either; it is a static (for want of a better phrase). In scala:
val j = 4
Map.empty
As far as the language is concerned, j
is an object (and I may dispatch methods to it), as is Map
- the module (or companion object) for the type scala.collection.immutable.Map
.
I thought everything is expression because the statement returns a value.
There are things that don't have values, but for the most part, this is correct. That means that we can basically drop the distinction between "statement" and "expression" in Scala.
The term "returns a value" is not quite fitting, however. We say everything "evaluates" to a value.
But I also heard that everything is an object in scala.
That doesn't contradict the previous statement at all :) It just means that every possible value is an object (so every expression evaluates to an object). By the way, functions, as first-class citizens in Scala, are objects, too.
Why did scala choose to do it one way or the other?
It has to be noted that this is in fact a generalization of the Java way, where statements and expressions are distinct things and not everything is an object. You can translate every piece of Java code to Scala without a lot of adaptions, but not the other way round. So this design decision makes Scala is in fact more powerful in terms of conciseness and expressiveness.
What does that mean to a scala developer?
It means, for example, that:
return
, because you can just put the return value as the last expression in a methodif
and case
are expressions to make your code shorterAn example would be:
def mymethod(x: Int) = if (x > 2) "yay!" else "too low!"
// ...
println(mymethod(10)) // => prints "yay!"
println(mymethod(0)) // => prints "too low!"
We can also assign the value of such a compound expression to a variable:
val str = value match {
case Some(x) => "Result: " + x
case None => "Error!"
}