I’m puzzled by something in Scala. I seem to have objects that have the same address, but different contents. I came across this issue while using Kiama. But to keep things simple, I boiled all the code down to this:
object CaseTests {
trait Attributable extends Product {
var parent: Attributable = null;
private def setChildConnections = {
var i : Int = 0
for (i <- 0 until productArity) {
productElement (i) match {
case c : Attributable => c.parent = this
case _ =>
}
}
}
setChildConnections
}
abstract class Tree extends Attributable { def id = super.toString }
case class Pair (left : Tree, right : Tree) extends Tree { println(this+" = "+super.toString + " = ("+left.id+", "+right.id+")"); }
case class Leaf (value : Int) extends Tree { println(this+" = "+super.toString); }
def main(args: Array[String]): Unit = {
val l1 = Leaf(1);
val l2 = Leaf(1);
val tree = Pair (Leaf (1), Pair (Leaf (1), Leaf (2)))
val Pair(left1: Tree, sub: Tree) = tree
val Pair(left2: Tree, right: Tree) = sub
println("left1 = "+left1.id)
println("left2 = "+left2.id)
println("left1.parent = "+left1.parent)
println("left2.parent = "+left2.parent)
}
}
When I run my test case, I get this as output:
Leaf(1) = org.modelica.v4.tests.full.CaseTests$Leaf@fe67d8d2
Leaf(1) = org.modelica.v4.tests.full.CaseTests$Leaf@fe67d8d2
Leaf(1) = org.modelica.v4.tests.full.CaseTests$Leaf@fe67d8d2
Leaf(1) = org.modelica.v4.tests.full.CaseTests$Leaf@fe67d8d2
Leaf(2) = org.modelica.v4.tests.full.CaseTests$Leaf@de2f8005
Pair(Leaf(1),Leaf(2)) = org.modelica.v4.tests.full.CaseTests$Pair@d8e41584 = (org.modelica.v4.tests.full.CaseTests$Leaf@fe67d8d2, org.modelica.v4.tests.full.CaseTests$Leaf@de2f8005)
Pair(Leaf(1),Pair(Leaf(1),Leaf(2))) = org.modelica.v4.tests.full.CaseTests$Pair@6a311526 = (org.modelica.v4.tests.full.CaseTests$Leaf@fe67d8d2, org.modelica.v4.tests.full.CaseTests$Pair@d8e41584)
left1 = org.modelica.v4.tests.full.CaseTests$Leaf@fe67d8d2
left2 = org.modelica.v4.tests.full.CaseTests$Leaf@fe67d8d2
left1.parent = Pair(Leaf(1),Pair(Leaf(1),Leaf(2)))
left2.parent = Pair(Leaf(1),Leaf(2))
What I don’t understand (and I suspect this is because I am missing some subtle point about equivalence in Scala/Java or perhaps I’m simply misinterpreting the output) is how left1 and left2 appear to have the same address (or am I misinterpreting that), but different parents?!
If somebody could set me straight, I would really appreciate it. Thanks.
P.S. – I’m running Scala 2.9, in case it matters.
left1andleft2are not the same objects. Tryprintln(left1 eq left2), it will print false. The defaulttoStringmethod callsInteger.toHexString(hashCode), so you’re bound to get the sameidif the hash code of two object matches. And here it does, because case classes automatically get a decenthashCodeandequalsimplementation.