I just read this question and stumbled upon the following quote:
Scala treats == as if it were defined as follows in class Any:
final def == (that: Any): Boolean =
if (null eq this) (null eq that) else (this equals that)
The (null eq this) part made me wonder: Is it actually possible to call methods on null pointers? Can this be null in Scala?
Check out the Scala language specification, namely 6.3 The Null Value chapter:
The null value is of type scala.Null, and is thus compatible with every reference
type. It denotes a reference value which refers to a special “null” object. This object
implements methods in class scala.AnyRef as follows:
• eq(x) and ==(x) return true if the argument x is also the “null” object.
• ne(x) and !=(x) return true if the argument x is not also the “null” object.
This means that semantically when you compare something with null literal or null literal with something you are actually referring to method of a special scala.Null class. Treat null literal as a shorthand for that class.
Of course at the implementation level it is optimized and ordinary null is used.
null is the only instance of Null class and it's a valid object. Null is a subtype of all reference types.
I'm pretty new to Scala, but the only way I see that as being possible is due to the fact that "null" itself is an instance of Null, and not exactly a special value like "null" in Java.
http://blog.sanaulla.info/2009/07/12/nothingness/
This article helped me understand this a bit better.
Related
On dart tour page (https://dart.dev/guides/language/language-tour#getting-an-objects-type) these have a statement that testing variable type with "is" expression is more stable. Why is it so?
An is test is a subtype test.
If you do e is Iterable, you check whether the value of e implements Iterable<dynamic>, which includes any of List, Set and Queue, as well as all the subtypes of Iterable used internally by the runtime system, like _TakeIterable (which is used to implement Iterable.take).
It matches both values of type Iterable<Object> and Iterable<int>.
All of these are objects which can safely be used as an Iterable, and are intended to be used as such.
If you do e.runtimeType == Iterable, you are checking whether the Type object returned by e.runtimeType is equal to precisely the type Iterable<dynamic>. That will be false for any list, set or queue, for any actual iterable class which only implements Iterable, and even for something which returns the Type object of Iterable<int> or Iterable<Object?> from runtimeType.
I say that you check the object returned by e.runtimeType, not the run-time type of the value, because anyone can override the runtimeType getter.
I can make a class like:
class WFY {
Type get runtimeType => Iterable<int>;
}
void main() {
print(WFY().runtimeType == Iterable<int>); // True!
}
The value returned by runtimeType doesn't have to have any relation to the actual runtime type of the object.
Obviously it usually has, because there is no benefit in overriding runtimeType, because you shouldn't be using it for anything anyway,
Even if your code works today, say:
assert(C().runtimeType == C); // Trivial, right!
it might fail tomorrow if I decide to make C() a factory constructor which returns a subtype, _C implementing C.
That's a change that is usually considered non-breaking, because the _C class can do everything the C interface requires, other than having C as actual runtime type.
So, doing Type object checks is not stable.
Another reason using is is better than comparing Type objects for equality is that it allows promotion.
num x = 1;
if (x is int) {
print(x.toRadixString(16)); // toRadixString is on int, not on num
}
The is check is understod by the language, and trusted to actually guarantee that the value's runtime type implements the type you check against.
Comparing Type objects can mean anything, so the compiler can't use it for anything.
Some people like to use runtimeType in their implementation of ==, like;
class MyClass {
// ...
bool operator ==(Object other) =>
MyClass == other.runtimeType && other is MyClass && this.x == other.x;
}
This is intended to avoid subclass instance being equal to super-class instances when you ask the superclass, but not if you ask the subclass (the "ColorPoint problem", where ColorPoint extends Point with a color, and is equal to a another ColorPoint with the same coordinates and color, but if you ask a plain Point whether it's equal to a ColorPoint, it only checks the coordinates.)
This use of runtimeType "works", but is not without issues.
It means you cannot use mocks for testing.
It means you cannot create a subclass which doesn't extend the state, only the behavior, and which would want to be equal to the superclass instances with the same state.
And it means you do extra work, because you still need to cast the other object from Object to the surrounding type in order to access members, and Type object checks do not promote.
If possible, it's better to never allow subclasss of a concrete class that has a == method, and if you need to share other behavior, inherit that from a shared superclass.
(In other words: Don't extend classes that aren't intended to be extended, don't put == on classes which are intended to be extended.)
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
From the API doc I found that Null is a trait, but it says its sole instance is null.
abstract final class Null extends AnyRef
Null is - together with scala.Nothing - at the bottom of the Scala type hierarchy.
Null is a subtype of all reference types; its only instance is the null reference. Since Null is not a subtype of value types, null is not a member of any such type. For instance, it is not possible to assign null to a variable of type scala.Int.
How is it possible to instantiate a trait? Any simple example to realize this concept would really helpful.
You cannot instantiate an instance of the class Null, as it is abstract and final. Null is a figment of the compiler similar Nothing, used as a bottom-type for all reference types. That is, Null is a sub-type of any other type that inherits from AnyRef. Its only value is the null reference, but there is no way to instantiate the Null class and magically get a null reference. It differs from Nothing in that it is inhabited by a single value: null.
Therefore, if you assign null to an identifier, Null will be inferred as its type if you don't hint otherwise.
scala> val a = null
a: Null = null
I am new to scala. Please help me to understand below code snippet
null.==("goutam") // ---> return false
null.equals("goutam") // ---> throw NullPointerException
As per my understanding null is the only instance of Null trait which extends Anyref and == and equals both are functions of AnyRef. so why first statement does not throw but second one does?
Why first statement does not throw but second one does
Per the language specification (6.3), there are specific methods on null which will not cause a NullReferenceException to occur if invoked. They're defined as:
6.3 The Null Value
The null value is of type scala.Null, and is thus
compatible with every reference type. It denotes a reference value
which refers to a special “null” object. This object implements
methods in class scala.AnyRef as follows:
eq(x) and ==(x) return true iff the argument x is also the "null"
object.
ne(x) and !=(x) return true iff the argument x is not also the
"null" object.
isInstanceOf[T] always returns false.
asInstanceOf[T] returns the default value of type T.
## returns 0.
A reference to any other member of the "null" object causes a NullPointerException to be thrown.
equals is defined on AnyRef and doesn't handle null values as per definition. eq, which checks for reference equality (that's usually not what you want to do) can be used:
scala> null.==("goutam")
res0: Boolean = false
scala> null.eq("goutam")
res1: Boolean = false
== does handle null properly, and that is what you should be using. More on that in Whats the difference between == and .equals in Scala?
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