Wednesday, April 30, 2014

var, val and equality in Scala

Scala is a unique language and there are a number of reasons for saying so. One of the design goals has been to provide the end users  with options and choices. The old saying goes that if all you have is a hammer everything looks like a thumb (nail for non-programmers and thumbnail for graphic designers) . Scala is a multi-paradigm and allows you to design and implement object oriented, pure functional or a mix of the two. One place where this multitude of paradigms is most evident is the variable definition. If you want to declare an integer you have these choices –
val aInt : Int = 5
var bInt : Int = 4
val cInt = 3
var dInt = 2

Something as simple as variable declaration has some noteworthy features in Scala . First of all note that there is a val (short for value) and var (short for variable). If you are coming from a pure functional programming background such as Haskell, you are about to get some shocking news. A val is an immutable value, meaning the variable declared as val cannot undergo assignment at a later point. A var on the other hand is ‘regular’ variable, or rather what would be considered ‘regular’ in Java or C++. A var can undergo mutations and can be re-assigned at a later point.  Scala , being a language decidedly leaning towards functional style of programming, encourages and prefers val over var.  In Scala , if you find yourself declaring too many var variables, you probably need to go back to drawing board. This bias is further evident in most of the Scala editors and IDEs which display your var in red color, urging you to think again about these variables.
The same argument also applies for reference types. So, if you have a reference type that is declared as val, all it means that the variable will always keep pointing to the same area(object) in memory. There are no guarantees of the immutability of the object itself. A var reference type can, by the same logic, start pointing to some other object. Let’s take this with an example –
case class Person(firstName:String, lastName:String)
defined class Person
Let’s create some instances –
Scala > val p1 = Person("Hamid", "Karzai")
p1: Person = Person(Hamid,Karzai)

Scala > val p2 = Person("Atal Bihari", "Vajpayee")
p2: Person = Person(Atal Bihari,Vajpayee)
Scala > val p3 = Person("Atal Bihari", "Vajpayee")
p3: Person = Person(Atal Bihari,Vajpayee)

The above code instantiates two Person s – Karzai and Vajpayee. Obviously, they are different and so you would expect the following -
Scala > p1 == p2
res67: Boolean = false

Scala > p3== p2
res68: Boolean = true
What you might find unexpected is the following-
Scala > p3 eq p2
res69: Boolean = false

Scala > p3 eq p3
res70: Boolean = true
The opposite of eq operator is the ne operator -
  Scala > p3 ne p1
res71: Boolean = true

Scala > p3 ne p2
res72: Boolean = true
As you might have guessed by now, Scala uses == operator for equality comparison by value.  Identity comparison is a ‘code smell’, but if you must you can use the eq operator. The ne operator is the opposite of eq operator. It would be instructive to recall that Java has the opposite syntax with == doing the identity comparison and .equals method (defined in object) taking the onus of comparison by value.
There is more to this equality comparison though. Consider this –
class Leader(f: String, l: String) {
  val firstName: String = f
  val lastName: String = l
}
scala> val abp : Leader = new Leader("Atal Bihari", "Vajpayee")
abp: Leader = Leader@d86edfb

scala> val abp2 : Leader = new Leader("Atal Bihari", "Vajpayee")
abp2: Leader = Leader@7588262d

scala> abp == abp2
res73: Boolean = false

scala> abp eq abp2
res74: Boolean = false
There is no difference in the behavior of == or eq. The difference this time is that Leader is not a case class. There is a separate post on traits, class, object and companion objects, so stay tuned. Before leaving the topic it is essential to point out that ==, != are defined in class Any – the top most class in Scala . It would instructive to also look at couple of other methods that return the hashcode defined in Any class - ## and hashCode. Let us invoke them on “Hello World!”
Scala > "Hello World!" ##
warning: there were 1 feature warning(s); re-run with -feature for details
res4: Int = -969099747

Scala > "Hello World!" hashCode
warning: there were 1 feature warning(s); re-run with -feature for details

res5: Int = -969099747

No comments:

Post a Comment