views:

412

answers:

4

As far as I understand, Scala's == defines the natural equality of two objects.

I expected that Array(0,1,2) == Array(0,1,2) compares the natural equality e. g. checks if all elements of the array return true when compared with the corresponding elements of the other array.

People told me that Scala's Array is just a Java [] which only compares identity. Wouldn't it be more meaningful to override Array'sequals method to compare natural equality instead?

Thank you for your thoughts!

Thank you all for your answers! Is there a recommended way to choose which answer gets the "tick" if there is more than one good accurate answer?

+3  A: 

== in Scala is equivalent to Object.equals in Java.

You're asking for the equality of an array, which is different from the equality of a list.

When comparing arrays, you're doing exactly what incrediman says above.

jgg
In case somebody is wondering where the different equalities come from: Arrays don't override Object.equals, lists do.
meriton
Wouldn't it be nicer if `Array` overrides `equals` to represent natural equality so that `equals` and `eq` actually do different things?
soc
Scala's Array (in 2.8) is the JVM array. We must live with what those arrays provide.
Randall Schulz
Array.scala seems to add many methods not available to a standard Java Array, why is it not possible then to override equals there?
soc
Because it only _seems_ to add them, especially in 2.8. (2.7 already ran into trouble trying to get fancier with `Array` than the JVM really allowed.) If you call a method on `Array` that doesn't actually exist, it will implicitly wrap it for you. But this makes it obvious why you can't override `equals`: it does actually exist, so you wouldn't know you had to wrap it then. (For performance reasons, wrapping it every time is a bad idea also.)
Rex Kerr
+4  A: 

But Scala's String is also just a Java String but Scala overrides equals to compare natural equality.

Scala doesn't override anything there; java.lang.String has a value-dependant implementation of equals() (like many other Java classes, but unlike arrays).

Michael Borgwardt
Hi Michael, thanks! I fixed my question accordingly. Basically I just wonder why equals is not overridden to return natural equality like the Collection classes (I know that Array does not belong to the Collection classes!).
soc
Scala interprets `==` as `equals`. That's all. `String` has an `equals` that does something usefully different from reference identity. `[]` does not.
Rex Kerr
+13  A: 

Scala 2.7 tried to add functionality to Java [] arrays, and ran into corner cases that were problematic. Scala 2.8 has declared that Array[T] is T[], but it provides wrappers and equivalents.

Try the following in 2.8 (edit/note: as of RC3, GenericArray is ArraySeq--thanks to retronym for pointing this out):

import scala.collection.mutable.{GenericArray=>GArray, WrappedArray=>WArray}
scala> GArray(0,1,2) == GArray(0,1,2)
res0: Boolean = true

scala> (Array(0,1,2):WArray[Int]) == (Array(0,1,2):WArray[Int])
res1: Boolean = true

GenericArray acts just like Array, except with all the Scala collections goodies added in. WrappedArray wraps Java [] array; above, I've cast a plain array to it (easier than calling the implicit conversion function) and then compared the wrapped arrays. These wrappers, though backed by a [] array, also give you all the collection goodies.

Rex Kerr
Are there any performance/memory/typing/... benefits from using these classes instead of e. g. a List then? I could imagine that GenericArray/WrappedArray add quite a bit of overhead ...
soc
No, actually, they add very little overhead--`WrappedArray` is one extra class wrapped around a plain Java array. `List` requires an extra class around _every single element_. You use lists because of ease of use and cool pattern matching and immutability, not for efficiency. `GenericArray` has a slightly odd position, though, as a fixed-size array: the size is immutable but the contents are mutable. Why, one might wonder, not just use an `ArrayBuffer`?
Rex Kerr
@Rex Kerr You can very well use an immutable List because of performance. Immutable collections can save you from having to make defensive copies. Depending on the application this can outweigh their overhead.
ziggystar
@ziggystar: This is occasionally true, I agree, though I've yet to run across a single case in my own code--it has always been faster to do something else, but often _so_ much more work that I wouldn't bother. Immutable lists often do very well in the (coding time required)/(execution time taken) ratio.
Rex Kerr
`GenericArray` is now called `ArraySeq`
retronym
+3  A: 

Scala doesn't override Array's equality because it's not possible. One can only override methods when subclassing. Since Array isn't being subclassed (which isn't possible), Scala cannot override its methods.

Daniel