26

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. For example, 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?

soc
  • 27,983
  • 20
  • 111
  • 215
  • I'm not familiar with Scala. However, are you sure == isn't comparing whether or not the arrays are aliases (references to the same object in memory)? I'm assuming this is a possibility, since you mentioned it being related to a Java array. – Cam Mar 19 '10 at 23:27
  • 1
    It's an unfortunate situation, as the other answers describe, but when you know you're dealing with Array, you can use sameElements and get the answer you want while avoiding all the wrapping and boxing and circumlocutions. – Randall Schulz Jun 06 '10 at 04:31

3 Answers3

20

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
  • 166,841
  • 26
  • 322
  • 407
  • 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 Mar 20 '10 at 00:35
  • 1
    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 Mar 20 '10 at 01:12
  • 1
    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 Mar 22 '10 at 07:53
  • @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 Mar 22 '10 at 14:46
  • 2
    `GenericArray` is now called `ArraySeq` – retronym Jun 06 '10 at 06:50
  • @RexKerr Why use a (coding time required)/(execution time taken) ratio? Wouldn't we want to aim for low coding time AND low execution time? Maybe codingTime * execTime with lower being better, or constant / (codingTime * execTime) where higher would be better. – J.D. Sandifer Feb 03 '19 at 15:39
  • @J.D.Sandifer - You're right, of course. I meant "execution speed", not "execution time". (I wanted it to be a ratio because in that form it's clearer what the tradeoff is.) – Rex Kerr Feb 15 '19 at 15:13
9

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 C. Sobral
  • 295,120
  • 86
  • 501
  • 681
5

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
  • 342,105
  • 78
  • 482
  • 720
  • 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 Mar 20 '10 at 00:06
  • 3
    Scala interprets `==` as `equals`. That's all. `String` has an `equals` that does something usefully different from reference identity. `[]` does not. – Rex Kerr Mar 20 '10 at 16:02