2012-08-09 34 views
7

Sé que el método == en Scala tiene la misma semántica del método equals en Java. Sin embargo, me gustaría entender cuando se aplica a instancias de estructuras recursivas. Por ejemplo, considere un montón de expresiones:Método Scala y == en los tipos recursivos definidos

abstract class Exp 

abstract class BinaryExp(l:Exp, r:Exp) extends Exp 

case class Plus(l:Exp, r:Exp) extends BinaryExp(l,r) 

case class Minus(l:Exp, r:Exp) extends BinaryExp(l,r) 

case class Mult(l:Exp, r:Exp) extends BinaryExp(l,r) 

case class Div(l:Exp, r:Exp) extends BinaryExp(l,r) 

case class Num(v:Int) extends Exp 

Entonces, cuando tengo dos instancias de un BinaryExp, dicen obj1 y obj2, hace obj1 == obj2 resultado en una prueba de igualdad profunda (recursivo)? Es decir, ¿está garantizado que si se cumple obj1 == obj2, entonces obj1 y obj2 representan los mismos árboles de expresión exacta?

Tenga en cuenta que en todas las clases, confío en la implementación predeterminada de == (no se reemplaza en ninguna parte).

Respuesta

14

Esto es fácil de probarse a sí mismo:

val x = Plus(Num(1), Num(2)) 
val y = Plus(Num(1), Num(2)) 
val z = Plus(Num(1), Num(3)) 

println(x == y) // prints true 
println(x == z) // prints false 

El hecho de que estos dan las respuestas correctas muestra que la comprobación de igualdad es la comprobación de la igualdad "profunda" de subexpresiones.

Por otra parte, se puede ver en el documentation que: método

Para cada clase caso el compilador Scala genera es igual que implementa la igualdad estructural

"igualdad estructural" es el tipo de verificación profunda de la igualdad que te estás preguntando.

Finalmente, si realmente desea ver qué sucede más allá del azúcar sintáctico, puede usar la opción -xPrint:typer cuando ejecuta scalac o inicia REPL. Si utiliza esta opción con el REPL y luego declara la clase Plus, aquí es lo que obtienes (abreviado):

scala> case class Plus(l:Exp, r:Exp) extends BinaryExp(l,r) 
[[syntax trees at end of typer]]// Scala source: <console> 
... 
case class Plus extends $line2.$read.$iw.$iw.BinaryExp with ScalaObject with Product with Serializable { 
    ... 
    override def equals(x$1: Any): Boolean = Plus.this.eq(x$1.asInstanceOf[java.lang.Object]).||(x$1 match { 
    case (l: $line1.$read.$iw.$iw.Exp, r: $line1.$read.$iw.$iw.Exp)$line3.$read.$iw.$iw.Plus((l$1 @ _), (r$1 @ _)) if l$1.==(l).&&(r$1.==(r)) => x$1.asInstanceOf[$line3.$read.$iw.$iw.Plus].canEqual(Plus.this) 
    case _ => false 
    }); 

Así, enterrado en el primer case verá que Plus.equals está llamando if l$1.==(l).&&(r$1.==(r)) con el fin de comprobar igualdad. En otras palabras, el método de igualdad generado de una clase de caso llama al == en sus subexpresiones para verificar su igualdad.

Cuestiones relacionadas