开发者

Scala, Java and equality

开发者 https://www.devze.com 2023-01-10 23:33 出处:网络
val filesHere = (new java.io.File(\".\")).listFiles val filesHere2 = (new java.io.File(\".\")).listFiles
val filesHere = (new java.io.File(".")).listFiles
val filesHere2 = (new java.io.File(".")).listFiles

scala> filesHere == filesHere2

res0: Boolean = false

That is quite counter intuitive. I would rather expect that filesHere and filesHere2 are equal.

This is certainly due to a semantics mismatch between Java and Scala, e.g., about arrays or (f开发者_开发问答iles) equality. Clearly, I am missing something here!


If I ruled the world, I would deprecate Scala's eq method on the grounds that the name is extremely confusible with equals and ==. Instead English does have a word which expresses identity as opposed to equality: I would simply call it is .

Similarly I would replace Scala's ne (which is a terrible name, since it's both an abbreviation and incomprehensible) with isnt .

Seems to me these could actually be added to AnyRef and the old methods deprecated, even at this late stage.


The equals() method of Java arrays uses reference equality rather than anything more sophisticated, and Scala's == is simply Java's equals().


The comparison doesn't work as expected, because this Java API returns an Array.

Scala's arrays and Java arrays are the same behind the scenes and although Scala's array looks like a class it is just a java.io.File[] (in this example).

This is the reason why the check for equality can't be overridden. Scala has to use Java semantics for it.

Consider this example:

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

This would work as expected.


You may want to read through here:

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

but it appears that if you did: filesHere.sameElements(filesHere2) that it should be true.

The javadoc for this is here: http://www.scala-lang.org/api/2.6.0/scala/IterableProxy.html#sameElements%28Iterable%5BB%5D%29

UPDATE:

A couple of snippets from the first link that may be helpful:

In Java, C++, and C# the == operator tests for reference, not value equality. In contrast, Ruby’s == operator tests for value equality. Whatever language you’re used to, make sure to remember that in Scala, == is testing for value equality.

In reference to == not working as expected on Lists:

While this may seem like an inconsistency, encouraging an explicit test of the equality of two mutable data structures is a conservative approach on the part of the language designers. In the long run, it should save you from unexpected results in your conditionals.

UPDATE 2:

Based on comments from Raphael I looked at the specification, and it was dated two days ago for the most recent update, and I see these at 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

So, it appears that the definition hasn't changed in Scala 2.10.2, as the specification seems to be consistent. If the behavior is different, then if you write a unit test it should be sent as a bug for Scala.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号