I am trying to assign null to a variable which is Double like this:
var foo = 0.0
foo = null
However, this gives an error that null cannot be implicitly converted to Double
So I do this instead:
foo = null.asInstanceOf[Double]
however the new value for foo is 0.0
How can I set the value to null?
You can't. Double is a value type, and you can only assign null to reference types. Instead, the Scala compiler replaces null with a default value of 0.0.
See default values in the SLS 4.2:
default type
0 Int or one of its subrange types
0L Long
0.0f Float
0.0d Double
false Boolean
You cannot assign Java primitives to null, either. And while Scala's Double isn't truly a primitive (it is actually a class in Scala), it needs to compile down to double in Java byte code. Instead, you should use Option[Double] if you want to represent a value that is missing entirely, and try to never use null in Scala.
An alternative (perhaps easiest) approach is just to use java.lang.Double instead of scala.Double, and assign to java.lang.Double.NaN instead of null.
Then you can just do
if(foo.isNaN) { work around not a number case } else { usual case }
when using the variable.
I say this is perhaps easiest because if your intention is to be able to check for Not-Available (or non-existing) status of a Double value, while otherwise using the variable(s) with usual Double arithmetic & operators, then using the java float primitives is quite a bit simpler than aliasing and otherwise working around the wrapper class of Option[Double].
See: Option[Double] arithmetic operators
and Can float (or double) be set to NaN?
To answer your question why the complier complain when assigning a null to double variable, you can easily understand via the scala classes hierarchy diagram:
http://docs.scala-lang.org/tutorials/tour/unified-types.html
In short,
Double is a sub class of Anyval
null (a instance of Null) is a sub class of AnyRef.
So they are different types or classes in scala, it is similar to assign a List to a String.
You should never use null in Scala, instead take a look at Option, Option[Double] specifically
val foo = Some(0.0)
foo = Option.empty[Double]
Even Java introduced it's Optional values, instead of null.
https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
http://www.scala-lang.org/api/2.7.4/scala/Option.html
Related
I'm new in scala, and while trying to understand below code, found lot of doubts. Please help me to understand this
There is one scala file named as MyEnums.scala, and code present within it as follow
object AllEnums extends Enumeration {
type Enums = Value
val one,two,three = Value
def getAllValues() : String = values.mkString(",")
}
I'm new in scala, also bit confused same enumeration logic in Java too. Trying to understand how enum defined here.
Is AllEnums is a object of class MyEnums.scala ?
If 1 point is correct that means, MyEnums.scala extending class MyEnums.scala ?
type Enums = Value, Value is type in scala, what's a real significance of it and what this statement type Enums = Value is doing in code ?
val one,two,three = Value, In this statment Is = Value means the values assigned to val one,two,three are of type Value ?
val one,two,three, Are these instance variables of class MyEnums.scala, whic is nothing but of Enumeration Type ?
what's a type of these vals one,two,three ? Assigning values to these are of Value type, but is there any type of these variables itself one,two,three ?
Is AllEnums is a object of class MyEnums.scala ?
No
If 1 point is correct that means, MyEnums.scala extending class MyEnums.scala ?
No
type Enums = Value, Value is type in scala, what's a real significance of it and what this statement type Enums = Value is doing in code ?
type Enums = Value makes Enums an alias of Value.
As for "significance" of it, I am not sure how to answer that. What is the "real significance" of Boolean?
val one,two,three = Value, In this statment Is = Value means the values assigned to val one,two,three are of type Value ?
Yes
val one,two,three, Are these instance variables of class MyEnums.scala, whic is nothing but of Enumeration Type ?
MyEnums.scala is a file, not a class.
one, two, three are members of AllEnums, and it certainly is not "nothing".
what's a type of these vals one,two,three ?
It is Value as you said yourself above. Or Enums, which is the same as. Value.
Assigning values to these are of Value type, but is there any type of
these variables itself one,two,three ?
Yes. Value.
Why doesn't this work?
trait testtrait[T] {
var ob:T = null
}
then scalac testtrait.scala produces
testtrait.scala:2: error: type mismatch;
found : Null(null)
required: T
var ob:T = null
^
one error found
I'm using Scala 2.9
I can't say why exactly, but underscore notion (which is shortcut for default value for type, which is null for objects) will work fine:
trait testtrait[T] {
var ob:T = _
}
More dreaded workaround is asInstanceOf cast, but I found underscore better alternative.
trait testtrait[T] {
var ob:T = null.asInstanceOf[T]
}
null is a value of type Null, but not any type has Null as a subtype, only AnyRef-derived ones (except Nothing, of course). Suppose that you did something like
object SomeObj extends testtrait[Int]
What SomeObj.ob should be equal to? It is an Int, so it does not have null as a possible value.
As it is said in other answers, you should use underscore syntax to set default value for the type.
The bottom type of all types is Nothing. That means any type T, not otherwise constrained, can be Nothing, and null is not a Nothing (in fact, no value is).
So, to be able to assign null, you'd have to write it [T >: Null] (T is a supertype of Null).
On the other hand, you can initialize it to the default value using var ob: T = _. However, be aware that for any AnyVal, T will be boxed and assigned null instead of, say, 0, which can lead to unexpected results.
Is it possible for a pattern match to detect if something is a Numeric? I want to do the following:
class DoubleWrapper(value: Double) {
override def equals(o: Any): Boolean = o match {
case o: Numeric => value == o.toDouble
case _ => false
}
override def hashCode(): Int = value ##
}
But of course this doesn't really work because Numeric isn't the supertype of things like Int and Double, it's a typeclass. I also can't do something like def equals[N: Numeric](o: N) because o has to be Any to fit the contract for equals.
So how do I do it without listing out every known Numeric class (including, I guess, user-defined classes I may not even know about)?
The original problem is not solvable, and here is my reasoning why:
To find out whether a type is an instance of a typeclass (such as Numeric), we need implicit resolution. Implicit resolution is done at compile time, but we would need it to be done at runtime. That is currently not possible, because as far as I can tell, the Scala compiler does not leave all necessary information in the compiled class file. To see that, one can write a test class with a method that contains a local variable, that has the implicit modifier. The compilation output will not change when the modifier is removed.
Are you using DoubleWrapper to add methods to Double? Then it should be a transparent type, i.e. you shouldn't be keeping instances, but rather define the pimped methods to return Double instead. That way you can keep using == as defined for primitives, which already does what you want (6.0 == 6 yields true).
Ok, so if not, how about
override def equals(o: Any): Boolean = o == value
If you construct equals methods of other wrappers accordingly, you should end up comparing the primitive values again.
Another question is whether you should have such an equals method for a stateful wrapper. I don't think mutable objects should be equal according to one of the values they hold—you will most likely run into trouble with that.
What is the difference between == and .equals() in Scala, and when to use which?
Is the implementation same as in Java?
EDIT: The related question talks about specific cases of AnyVal. The more general case is Any.
You normally use ==, it routes to equals, except that it treats nulls properly. Reference equality (rarely used) is eq.
TL;DR
Override equals method to compare content of each instance. This is the same equals method used in Java
Use == operator to compare, without worrying about null references
Use eq method to check if both arguments are EXACTLY the same reference. Recommended not to use unless you understand how this works and often equals will work for what you need instead. And make sure to only use this with AnyRef arguments, not just Any
NOTE: On the case of equals, just as in Java, it may not return the same result if you switch the arguments eg 1.equals(BigInt(1)) will return false where the inverse will return true. This is because of each implementation checking only specific types. Primitive numbers dont check if the second argument is of Number nor BigInt types but only of other primitive types
Details
The AnyRef.equals(Any) method is the one overridden by subclasses. A method from the Java Specification that has come over to Scala too. If used on an unboxed instance, it is boxed to call this (though hidden in Scala; more obvious in Java with int->Integer). The default implementation merely compares references (as in Java)
The Any.==(Any) method compares two objects and allows either argument to be null (as if calling a static method with two instances). It compares if both are null, then it calls the equals(Any) method on boxed instance.
The AnyRef.eq(AnyRef) method compares only references, that is where the instance is located in memory. There is no implicit boxing for this method.
Examples
1 equals 2 will return false, as it redirects to Integer.equals(...)
1 == 2 will return false, as it redirects to Integer.equals(...)
1 eq 2 will not compile, as it requires both arguments to be of type AnyRef
new ArrayList() equals new ArrayList() will return true, as it checks the content
new ArrayList() == new ArrayList() will return true, as it redirects to equals(...)
new ArrayList() eq new ArrayList() will return false, as both arguments are different instances
foo equals foo will return true, unless foo is null, then will throw a NullPointerException
foo == foo will return true, even if foo is null
foo eq foo will return true, since both arguments link to the same reference
== is a final method, and calls .equals, which is not final.
This is radically different than Java, where == is an operator rather than a method and strictly compares reference equality for objects.
There is an interesting difference between == and equals for Float and Double types: They treat NaN differently:
scala> Double.NaN == Double.NaN
res3: Boolean = false
scala> Double.NaN equals Double.NaN
res4: Boolean = true
Edit: As was pointed out in a comment - "this also happens in Java" - depends on what exactly this is:
public static void main(final String... args) {
final double unboxedNaN = Double.NaN;
final Double boxedNaN = Double.valueOf(Double.NaN);
System.out.println(unboxedNaN == unboxedNaN);
System.out.println(boxedNaN == boxedNaN);
System.out.println(boxedNaN.equals(boxedNaN));
}
This will print
false
true
true
So, the unboxedNan yields false when compared for equality because this is how IEEE floating point numbers define it and this should really happen in every programming language (although it somehow messes with the notion of identity).
The boxed NaN yields true for the comparison using == in Java as we are comparing object references.
I do not have an explanation for the equals case, IMHO it really should behave the same as == on unboxed double values, but it does not.
Translated to Scala the matter is a little more complicated as Scala has unified primitive and object types into Any and translates into the primitive double and the boxed Double as needed. Thus the scala == apparently boils down to a comparison of primitive NaN values but equals uses the one defined on boxed Double values (there is a lot of implicit conversion magic going on and there is stuff pimped onto doubles by RichDouble).
If you really need to find out if something is actually NaN use isNaN:
Java: https://docs.oracle.com/javase/7/docs/api/java/lang/Double.html#isNaN(double)
Scala: http://www.scala-lang.org/files/archive/api/2.11.8/index.html#scala.Double#isNaN():Boolean
In Scala == first check for Null values and then calls equals method on first object
I was working with a variable that I had declared as an Integer and discovered that > is not a member of Integer. Here's a simple example:
scala> i
warning: there were deprecation warnings; re-run with -deprecation for details
res28: Integer = 3
scala> i > 3
<console>:6: error: value > is not a member of Integer
i > 3
^
Compare that to an Int:
scala> j
res30: Int = 3
scala> j > 3
res31: Boolean = false
What are the differences between Integer and Int? I see the deprecation warning but it's unclear to me why it was deprecated and, given that it has been, why it doesn't have a > method.
"What are the differences between Integer and Int?"
Integer is just an alias for java.lang.Integer. Int is the Scala integer with the extra capabilities.
Looking in Predef.scala you can see this the alias:
/** #deprecated use <code>java.lang.Integer</code> instead */
#deprecated type Integer = java.lang.Integer
However, there is an implicit conversion from Int to java.lang.Integer if you need it, meaning that you can use Int in methods that take an Integer.
As to why it is deprecated, I can only presume it was to avoid any confusion over which kind of integer you were working with.
Integer gets imported from java.lang.Integer and is only for compatibility with Java. Since it is a Java class, of course it can't have a method called "<".
EDIT: You can mitigate this problem by declaring an implicit conversion from Integer to Int.
implicit def toInt(in:Integer) = in.intValue()
You'll still get deprecation warning though.
I think the problem you're seeing has has to do boxing/unboxing of value types and the use of the Java class Integer.
I think the answer is here: Boxing and unboxing in Scala. There is no implict unboxing in Scala. You've defined i as the Java class Integer but in the i > 3, the 3 is being treated and an int.
Integer is a Java class, java.lang.Integer. It's different from Java's primitive type int, which is not a class. It can't have < defined, because Java does not allow operators to be defined for classes.
Now, you might wonder why such a type exist at all? Well, primitive types cannot be passed as references, so you can't pass an int to a method expecting java.lang.Object, equivalent to Scala's AnyRef, for example. To do that, you put that int inside an Integer object, and then pass the Integer.
Integer gets imported from java.lang.Integer and is only for compatibility with Java. Since it is a Java class, of course it can't have a method called "<".
EDIT: You can mitigate this problem by declaring an implicit conversion from Integer to Int.