views:

96

answers:

2

Can anyone enlighten me as to why implicit type conversion does not work with ==?

Example:

class BitArray(l: Int, v: Long) {  
    val length = l  
    var value = v  
    def ==(that: BitArray) = value == that.value  
    def ==(integer: Long) = value == integer  
    def +(that: BitArray) = new BitArray(length,value+that.value )  
    def +(integer: Long) = new BitArray(length,value+integer )  
//...  
}  
object BitArray{
        implicit def longToBitArray(x : Long) = new BitArray(64,x)  
        def apply(v: Long) :BitArray = apply(64,v)  
}

Now I can do:

scala> BitArray(5) + 5  
res13: BitArray = 00000000000000000000000000001010  
scala> 5 + BitArray(5)   
res14: BitArray = 00000000000000000000000000001010  
scala> BitArray(5) == 5  
res15: Boolean = true  
scala> BitArray(5) == 6  
res16: Boolean = false  

BUT:

scala> 5 == BitArray(5)  
<console>:11: warning: comparing values of types Int and BitArray using `==' will   
always yield false  
       5 == BitArray(5)  
         ^  
res17: Boolean = false  
+4  A: 

To override the == operator, you should actually override the equals method:

override def equals(other: Any): Boolean = other match {
  case ba: BitArray => value == ba.value
  case _ => false
}

You can't make an instance of your BitArray equal to a Long and still obey the equals contract (ie. it won't be symmetric).

Ben Lings
Can you elaborate? Or point me ind the direction of some documentation of how equals works?Thanks
Troels Blum
+5  A: 

You are missing a fundamental aspect of Scala, which is how equality works.

Basically, all classes extending AnyRef implement the following method:

def   equals  (arg0: Any)  : Boolean   

And all classes implement the following method:

def   ==  (arg0: Any)  : Boolean

Now, you should override not ==, but equals. The method == will call equals, but Java code will use equals, not ==. This is not the cause of the problem you see, but it is important enough that I think it is worth mentioning.

Now, as to the implicit not working, remember that implicits are only looked for if there is no method that satisfy your code. However, Int's == can be compared with BitArray, as == receives an argument of type Any. Therefore, Int's equality method is called, and no implicit is looked for.

Daniel
Thanks for the very clear answer :-)
Troels Blum
Not so much a fundamental aspect of Scala, but an aspect of how the standard library is fundamentally broken.
Apocalisp
@Apocalisp I meant fundamental as in "you must know this if you want to use Scala".
Daniel