A var
is a reference variable, similar to variables in languages like Java. Different objects can be freely assigned to a var
, so long as the given object has the same type that the var
was declared with:
scala> var x = 1
x: Int = 1
scala> x = 2
x: Int = 2
scala> x = "foo bar"
<console>:12: error: type mismatch;
found : String("foo bar")
required: Int
x = "foo bar"
^
Note in the example above the type of the var
was inferred by the compiler given the first value assignment.
A val
is a constant reference. Thus, a new object cannot be assigned to a val
that has already been assigned.
scala> val y = 1
y: Int = 1
scala> y = 2
<console>:12: error: reassignment to val
y = 2
^
However, the object that a val
points to is not constant. That object may be modified:
scala> val arr = new Array[Int](2)
arr: Array[Int] = Array(0, 0)
scala> arr(0) = 1
scala> arr
res1: Array[Int] = Array(1, 0)
A def
defines a method. A method cannot be re-assigned to.
scala> def z = 1
z: Int
scala> z = 2
<console>:12: error: value z_= is not a member of object $iw
z = 2
^
In the above examples, val y
and def z
return the same value. However, a def
is evaluated when it is called, whereas a val
or var
is evaluated when it is assigned. This can result in differing behavior when the definition has side effects:
scala> val a = {println("Hi"); 1}
Hi
a: Int = 1
scala> def b = {println("Hi"); 1}
b: Int
scala> a + 1
res2: Int = 2
scala> b + 1
Hi
res3: Int = 2
Because functions are values, they can be assigned to val
/var
/def
s. Everything else works in the same manner as above:
scala> val x = (x: Int) => s"value=$x"
x: Int => String = <function1>
scala> var y = (x: Int) => s"value=$x"
y: Int => String = <function1>
scala> def z = (x: Int) => s"value=$x"
z: Int => String
scala> x(1)
res0: String = value=1
scala> y(2)
res1: String = value=2
scala> z(3)
res2: String = value=3