2010-09-17 12 views
22

En Programming in Scala los autores escriben que la función == de Scala compara igualdad de valores en lugar de igualdad de referencia.¿Por qué la función == de Array no es verdadera para Array (1,2) == Array (1,2)?

Esto funciona como se espera en las listas:

scala> List(1,2) == List(1,2) 
res0: Boolean = true 

Sin embargo, no funciona en arrays:

scala> Array(1,2) == Array(1,2) 
res1: Boolean = false 

Los autores recomiendan utilizar la función sameElements lugar:

scala> Array(1,2).sameElements(Array(1,2)) 
res2: Boolean = true 

Como explicación escriben:

Si bien esto puede parecer una incoherencia, alentar una prueba explícita de la igualdad de dos estructuras de datos mutables es un enfoque conservador por parte de los diseñadores del lenguaje. A la larga, debería salvarte de resultados inesperados en tus condicionales.

  1. ¿Qué significa esto? ¿De qué tipo de resultados inesperados están hablando? ¿Qué más podría esperar de una comparación de matriz que devolver verdadero si las matrices contienen los mismos elementos en la misma posición? ¿Por qué funciona igual en List pero no en Array?

  2. ¿Cómo puedo hacer que funcione la función igual en las matrices?

+0

También he notado esta explicación en este libro. No es correcto, mira mi propia respuesta a continuación. Aparte de este error, el libro es muy bueno. –

+0

Se podría decir brevemente lo que está sucediendo ya que, "Java define la igualdad de valores en las matrices como igualdad de referencia, no igualdad de elemento por elemento". –

+0

posible duplicado de [Comportamiento extraño del tipo de matriz] (http://stackoverflow.com/questions/3213368/strange-behaviour-of-the-array-type) – Suma

Respuesta

26

Es cierto que la explicación ofrecida en el libro es cuestionable, pero para ser justos, era más creíble cuando lo escribieron. Sigue siendo cierto en 2.8, pero tenemos que actualizar el razonamiento porque, como habrás notado, todas las demás colecciones hacen comparaciones de elementos, incluso si son mutables.

Se había derramado mucha sangre tratando de hacer que Arrays pareciera el resto de las colecciones, pero esta era una abstracción tremendamente goteante y al final fue imposible. Se determinó, correctamente, creo, que deberíamos ir al otro extremo y suministrar matrices nativas tal como son, usando maquinaria implícita para mejorar sus capacidades. Donde esto se cae de forma más notable es aString e igual, porque ninguno de ellos se comporta de manera razonable en Arrays, pero no podemos interceptar esas llamadas con conversiones implícitas porque están definidas en java.lang.Object. (Las conversiones solo ocurren cuando una expresión no escribe check, y esas siempre escriben check.)

Así que puede elegir su explicación, pero al final las matrices son tratadas fundamentalmente de manera diferente por la arquitectura subyacente y no hay forma de revisarlo sin pagar un precio en alguna parte. No es una situación terrible, pero es algo de lo que debes estar consciente.

+0

Entonces, ¿está diciendo que los diseñadores de idiomas no creen que esta incoherencia sea notablemente buena, sino que la vean como el compromiso menos doloroso? –

+6

Hablando por mi cuenta, la programación es poco, pero "compromisos menos dolorosos" no es que esto me impida disfrutar de ella. Y hablando en nombre del resto del mundo, diría que su paráfrasis es un buen resumen. – extempore

-3

Todo se trata de transparencia referencial. La idea es que si dos valores son ==, no debería importar cuál use para algo. Si tiene dos matrices con el mismo contenido, es evidente que importa cuál modifique, por lo que == devuelve falso, a menos que sean el mismo.

+0

¡Esto no es correcto! Scala implementa == para todas las colecciones, excepto para Array. Ver mi propia respuesta. –

+0

Pensé que usaría la función 'eq' para comparar referencias en Scala –

+0

Bueno, sí. Usa el método eq para hacer eso. Pero recuerde que cuando crea una clase, (no una clase de caso), entonces == comparará referencias si no anula equals(). –

7

Esta pregunta exacta ha sido expresada muchas veces (por mí también, vea Strange behaviour of the Array type).

Tenga en cuenta que SÓLO es la colección Array que no admite ==, todas las demás colecciones lo hacen. La causa principal es que Array ES el Java array.

+0

¿Por qué los diseñadores de idiomas eligieron Java 'array' para ser el' Array' predeterminado en lugar de 'ArraySeq' o' WrappedArray' que se comportaría como se esperaba? –

+1

@Stefan - Debido a que los demás tienen que encajonar tipos primitivos, y por lo tanto no se ejecutan tan rápido, que es exactamente cuando usted querría usar una matriz. Además, al usar código Java, que muchos hacen, abundan las matrices. Por lo tanto, el menor de los males es hacer que 'Array' sea la matriz de Java; el costo es que '==' se comporta de manera inconsistente. Además, no existe una opción obvia para 'Array' en caso contrario. ¿Debería ser 'ArraySeq'? ¿Qué tal 'ArrayBuffer'? Tal vez 'WrappedArray'? Cada uno de ellos tiene razones decentes para existir, pero ninguno es el candidato más obvio. –

+0

Entonces, usted dice que a) fue una elección de rendimiento b) Normalmente, no debería usar matrices en Scala de modo que no importa que su función 'igual' sea inconsistente. –

Cuestiones relacionadas