Scala seems to view Seqs with same values as a single object, but not the same as Arrays.
Seq behaves the same as List, Set.
scala> Array(1) == Array(1)
res2: Boolean = false
scala> Seq(1) == Seq(1)
res3: Boolean = true
Why does it happen? What's the reason behind?
This is because Array is essentially an alias for Java’s array, which implements equals as reference equality - only returning true if two variables point to the same array instance.
Array is the only Scala collection for which == checks for reference equality, for all others it delegates to .equals which checks for value equality.
Though, Scala 2.13 introduces immutable Arrays which behave as expected.
For now, you can use .sameElements or .deep to compare instead.
Related
scala> List(1,2,3) == List(1,2,3)
res2: Boolean = true
scala> Map(1 -> "Olle") == Map(1 -> "Olle")
res3: Boolean = true
But when trying to do the same with Array, it does not work the same. Why?
scala> Array('a','b') == Array('a','b')
res4: Boolean = false
I have used 2.8.0.RC7 and 2.8.0.Beta1-prerelease.
Because the definition of "equals" for Arrays is that they refer to the same array.
This is consistent with Java's array equality, using Object.Equals, so it compares references.
If you want to check pairwise elements, then use sameElements
Array('a','b').sameElements(Array('a','b'))
or deepEquals, which has been deprecated in 2.8, so instead use:
Array('a','b').deep.equals(Array('a','b').deep)
There's a good Nabble discussion on array equality.
The root cause the it is that fact that Scala use the same Array implementation as Java, and that's the only collection that not support == as equality operator.
Also, it's important to note that the chosen answer suggest equally sameElements and deep comparison when actually it's preferred to use:
Array('a','b').deep.equals(Array('a','b').deep)
Or, because now we can use == back again:
Array('a','b').deep == Array('a','b').deep
Instead of:
Array('a','b').sameElements(Array('a','b'))
Because sameElements won't for for nested array, it's not recursive. And deep comparison will.
What is the difference between val a=new String("Hello") and val a="Hello"
Example:
val a="Hello"
val b="Hello"
a eq b
res:Boolean=True
Similarly:
val a=new String("Hello")
val b=new string("Hello")
a eq b
res:Bolean=False
eq compares memory references.
String literals are put in a string constants pool, so in the first example they share the same memory reference. This is a behavior that comes from Java (scala.String is built on top of java.lang.String).
In the second example you're allocating two instances at runtime so when you compare them they're are at different memory locations.
This is exactly the same as Java, so you can refer to this answer for more information: What is the difference between "text" and new String("text")?
Now, if you want to compare their values (as opposed to their memory references), you can use == (or equals) in Scala.
Example:
val a = new String("Hello")
val b = new String("Hello")
a eq b // false
a == b // true
a equals b // true
This is different than Java, where == is an operator that behaves like eq in Scala.
Also note that == and equals are slightly different in the way the deal with null values (== is generally advised). More on the subject: Whats the difference between == and .equals in Scala?
First of all eq (and its opposite ne) are used for what is called reference equality.
The behavior you observed is the result of what's technically known as string interning and is the inherited behavior from Java. Scala makes use of java.util.String under the hood. You can observe this in the REPL:
scala> val s = "Hello World!"
s: String = Hello World!
scala> s.isInstanceOf[java.lang.String]
res1: Boolean = true
You can see a general explanation of eq, ne, and == here.
To learn about JVM string interning see this Wikipedia article.
Since Scala advocates avoiding the usage of null, I do not understand why the default values are null in this specific use-case. Can someone please explain this ?
scala> Array.ofDim[String](1)
res0: Array[String] = Array(null)
On the other-hand, defaults for other types seems to be fine.
scala> Array.ofDim[Double](1)
res1: Array[Double] = Array(0.0)
scala> Array.ofDim[Int](1)
res2: Array[Int] = Array(0)
scala> Array.ofDim[Boolean](1)
res3: Array[Boolean] = Array(false)
scala> Array.ofDim[Float](1)
res4: Array[Float] = Array(0.0)
UPDATE/EDIT:
Not that it is a big deal, I can map over the array and wrapping each element in Option and fold it by providing default value is "". I want to understand why this is the default behavior
ofDim can be used to create/provide an array, when you have to call a Java API for example which expects nulls.
Another use case might be performance, when every instance counts, since arrays are the only collection which is supported directly by the JVM.
If you want an initialized array, you can use fill:
val sa = Array.fill(5)("Hi")
It is because you declared an array of Strings. And a String's default value is null. (Remember that this String is a java.lang.String, whose default is null.)
I was reading through coming from SQL to Slick and it states to use === instead of == for comparison.
For example,
people.filter(p => p.age >= 18 && p.name === "C. Vogt").run
What is the difference between == and ===, and why is the latter used here?
== is defined on Any in Scala. Slick can't overload it for Column[...] types like it can for other operators. That's why slick needs a custom operator for equality. We chose === just like several other libraries, such as scalatest, scalaz, etc.
a == b will lead to true or false. It's a client-side comparison. a === b will lead to an object of type Column[Boolean], with an instance of Library.Equals(a,b) behind it, which Slick will compile to a server-side comparison using the SQL "a = b" (where a and b are replaced by the expressions a and b stand for).
== calls for equals, === is a custom defined method in slick which is used for column comparison:
def === [P2, R](e: Column[P2])(implicit om: o#arg[B1, P2]#to[Boolean, R]) =
om.column(Library.==, n, e.toNode)
The problem of using == for objects is this (from this question):
Default implementation of equals() class provided by java.lang.Object compares memory location and only return true if two reference variable are pointing to same memory location i.e. essentially they are same object.
What this means is that two variables must point to the same object to be equal, example:
scala> class A
defined class A
scala> new A
res0: A = A#4e931efa
scala> new A
res1: A = A#465670b4
scala> res0 == res1
res2: Boolean = false
scala> val res2 = res0
res2: A = A#4e931efa
scala> res2 == res0
res4: Boolean = true
In the first case == returns false because res0 and res1 point to two different objects, in the second case res2 is equal to res0 because they point to the same object.
In Slick columns are abstracted in objects, so having column1 == column2 is not what you are looking for, you want to check equality for the value a column hold and not if they point to the same object. Slick then probably translates that === in a value equality in the AST (Library.== is a SqlOperator("="), n is the left hand side column and e the right hand side), but Christopher can explain that better than me.
'==' compare value only and result in Boolean 'True' & 'False
'===' compare completely (i.e. compare value with its data types) and result in column
example
1=='1' True
1==='1' False
scala> List(1,2,3) == List(1,2,3)
res2: Boolean = true
scala> Map(1 -> "Olle") == Map(1 -> "Olle")
res3: Boolean = true
But when trying to do the same with Array, it does not work the same. Why?
scala> Array('a','b') == Array('a','b')
res4: Boolean = false
I have used 2.8.0.RC7 and 2.8.0.Beta1-prerelease.
Because the definition of "equals" for Arrays is that they refer to the same array.
This is consistent with Java's array equality, using Object.Equals, so it compares references.
If you want to check pairwise elements, then use sameElements
Array('a','b').sameElements(Array('a','b'))
or deepEquals, which has been deprecated in 2.8, so instead use:
Array('a','b').deep.equals(Array('a','b').deep)
There's a good Nabble discussion on array equality.
The root cause the it is that fact that Scala use the same Array implementation as Java, and that's the only collection that not support == as equality operator.
Also, it's important to note that the chosen answer suggest equally sameElements and deep comparison when actually it's preferred to use:
Array('a','b').deep.equals(Array('a','b').deep)
Or, because now we can use == back again:
Array('a','b').deep == Array('a','b').deep
Instead of:
Array('a','b').sameElements(Array('a','b'))
Because sameElements won't for for nested array, it's not recursive. And deep comparison will.