2010-08-06 25 views
7
val filesHere = (new java.io.File(".")).listFiles 
val filesHere2 = (new java.io.File(".")).listFiles 

Scala> filesHere == filesHere2
res0: Boolean = falseScala, Java y la igualdad

Eso es bastante contrario a la intuición. Prefiero esperar que los archivos Here y FilesHere2 sean iguales.

Esto se debe a una falta de correspondencia semántica entre Java y Scala, por ejemplo, sobre matrices o igualdad (de archivos). ¡Claramente, me falta algo aquí!

Respuesta

4

Es posible que desee leer aquí:

http://ofps.oreilly.com/titles/9780596155957/AdvancedObjectOrientedProgramming.html#EqualityOfObjects

pero parece que si lo hizo: filesHere.sameElements(filesHere2) que debería ser cierto.

el Javadoc para esto está aquí: http://www.scala-lang.org/api/2.6.0/scala/IterableProxy.html#sameElements%28Iterable%5BB%5D%29

ACTUALIZACIÓN:

Un par de fragmentos desde el primer eslabón que puede ser útil:

En Java, C++ y C# el operador == prueba para referencia, no para valor igualdad. Por el contrario, el operador = = de Ruby prueba la igualdad de valores. Independientemente del idioma al que esté acostumbrado, recuerde que en Scala, == está probando la igualdad de valores.

En referencia al == no funciona como se esperaba en Listas:

Si bien esto puede parecer una contradicción, fomentando una prueba explícita de la igualdad de las dos estructuras de datos mutables es un enfoque conservador por parte de la diseñadores de idiomas. A la larga, debería salvarte de resultados inesperados en tus condicionales.

ACTUALIZACIÓN 2:

Basándose en los comentarios de Rafael Miré a la especificación, y estaba fechada dos días antes de la actualización más reciente, y veo estos en http://www.scala-lang.org/files/archive/nightly/pdfs/ScalaReference.pdf:

Method equals: (Any)Boolean is structural equality, where two instances 
are equal if they both belong to the case class in question and they have equal 
(with respect to equals) constructor arguments. 

class AnyRef extends Any { 
    def equals(that: Any): Boolean = this eq that 
    final def eq(that: AnyRef): Boolean = . . . // reference equality 

Por lo tanto, parece que la definición no ha cambiado en Scala 2.10.2, ya que la especificación parece ser consistente. Si el comportamiento es diferente, entonces, si escribe una prueba unitaria, debe enviarse como un error para Scala.

+0

¡Buen recurso, gracias! Muestra cómo lidiar con el problema mencionado anteriormente (usando sameElements, OK!) Pero no explica por qué el problema (o la "sorpresa") ocurre como en scala> Array (1, 2) == Array (1 , 2) res0: booleano = falso – acherm

+0

@acherm - Es por eso que puse la actualización, la última cita del artículo debe explicar el por qué, para alentar las pruebas explícitas de igualdad. –

+0

Otra discusión interesante aquí: http://scalide.blogspot.com/2009/05/hashcode-equals-in-scala-28-collections.html Eso no aclara completamente la situación, pero ilustra que "la igualdad es una tema interesante, simplemente por la increíble variedad de interpretaciones que hay de él ". En cuanto a Array.scala (http://lampsvn.epfl.ch/trac/scala/browser/scala/tags/R_2_8_0_final/src//library/scala/Array.scala), el método equals() no está definido . – acherm

8

El método equals() de las matrices de Java usa igualdad de referencia en lugar de algo más sofisticado, y == de Scala es simplemente el equals() de Java.

+0

En Scala == y equals() son para igualdad de valores, y eq es para si dos objetos tienen igualdad de referencia. –

+1

@James sí, pero en este caso equals() se implementa para simplemente verificar la igualdad de referencia. Entonces, en este caso particular, (Scala's ==) == (Java ==) :) –

+0

Aquí hay un hilo interesante: http://scala-programming-language.1934581.n4.nabble.com/scala-Array-equality -td2001726.html Pero aun así, estoy realmente confundido. Si Scala == (o "igual") realmente llama al método equals() de Java (como parece ser el caso), este ejemplo rompe algo la elección de diseño del lenguaje Scala sobre la igualdad. Como programador de Scala, tengo que recordar la semántica de igualdad en Java y tener cuidado con todos los puntos difíciles. ¡Maldita sea! – acherm

17

Si yo gobernaba el mundo, yo desapruebo eq método de Scala con el argumento de que el nombre es muy confusible con iguales y ==. En cambio, el inglés tiene una palabra que expresa identidad en oposición a la igualdad: simplemente lo llamaría es.

mismo modo que sustituiría ne de Scala (que es un nombre horrible, ya que es a la vez una abreviatura e incomprensible) con isnt.

Me parece que estos podrían en realidad agregarse a AnyRef y los métodos antiguos se dejaron de usar, incluso en esta etapa tardía.

+3

Me gusta mucho esa idea. –

+3

Sí, es una buena idea, pero "es" es ambiguo con verificaciones de tipo como: obj es String, que es popular en otros idiomas, y por lo tanto confuso. – tuxSlayer

8

La comparación no funciona como se esperaba, porque esta API de Java devuelve una matriz.

Las matrices de Scala y las matrices de Java son las mismas detrás de las escenas y, aunque la matriz de Scala se parece a una clase, es solo java.io.File [] (en este ejemplo).

Esta es la razón por la cual no se puede anular la verificación de igualdad. Scala tiene que usar la semántica de Java para ello.

Considere este ejemplo:

val filesHere = (new java.io.File(".")).listFiles.toList 
val filesHere2 = (new java.io.File(".")).listFiles.toList 

esto iba a funcionar como se espera.

+0

Array (1, 2) == Array (1, 2) tampoco funciona – FUD

+0

@FUD sí, porque es una matriz. Pero si llama a '.toList' - comenzará a funcionar. Esto se debe a que se convertirá en una clase del mundo Scala, y las clases en Scala se definen con un mejor 'igual'. – VasyaNovikov

Cuestiones relacionadas