6

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?

cosmosa
  • 743
  • 1
  • 10
  • 23
  • This is not an exact duplicate, but I think it will answer your question: http://stackoverflow.com/questions/10749010/if-an-int-cant-be-null-what-does-null-asinstanceofint-mean. – Gordon Linoff Apr 02 '17 at 12:58

4 Answers4

15

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.

Michael Zajac
  • 55,144
  • 7
  • 113
  • 138
  • Good answer, but it's unclear to me why not to use null in Scala. Can't you assign null to Option[Double] ? – cosmosa Apr 03 '17 at 01:16
  • 1
    @cosmos1990 It's considered bad practice to use `null` just about _anywhere_. You can assign `null` to `Option[Double]`, but it would be a bad idea to do so. There are plenty of [blog](http://www.yegor256.com/2014/05/13/why-null-is-bad.html) [articles](https://www.lucidchart.com/techblog/2015/08/31/the-worst-mistake-of-computer-science/) that are beyond that scope of this question that can help explain why nulls should be avoided. – Michael Zajac Apr 03 '17 at 01:34
  • 2
    I think the prohibition against null usage is a bit overstated here. Null exists for a very good reason, as void does. Can it be misused? Of course, but so can conditional expressions. I agree with that blog article about alternatives, I just don't like vague statements like 'It's considered bad practice to use null just about anywhere'. – absmiths May 09 '18 at 15:21
  • By the way, if you want to use Option E.G. for a Boolean, make sure to use `val opt: Option[Boolean] = Option.empty` and not `val opt: Option[Boolean] = null` when you want to use a null-like construct. – absmiths May 09 '18 at 15:23
  • I know this is very late, but I'd like to provide some theoretical support for absmiths above. In ternary logic, "I don't know" is a valid option, and this is the basis for NULL in databases and the various ways it is combined with other values in SQL statements. None in Scala does not take place of this, because it implies that the non-existence of the value is known. Option is a great class because it lets you distinguish between "I know it is empty" from "I don't know its value", but null still has a role. Possibly Unknown should be a class like Option, but it isn't right now. – Jonathan Card Oct 14 '20 at 19:54
  • Just found Java 8 Optional. That's what I want. – Jonathan Card Oct 14 '20 at 20:42
3

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?

Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
B Custer
  • 241
  • 2
  • 7
  • I used this approach initially before switching to Option. The interaction between java object types like java.lang.Boolean and scala 'primitive' types like scala.Boolean are ugly to say the least. I would avoid it if at all possible. – absmiths May 09 '18 at 15:26
  • @absmiths NaN is a x86 supported value for floats, which for some reason the authors of Scala chose to abstract away. While it's the result of performing bad operations (divide by 0 etc) it's quite handy for keeping track of NAs in large datasets. I don't recommend abandoning Scala primitives in general, but Option can be an awkward construct. – B Custer May 09 '18 at 17:38
1

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

enter image description here

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.

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
Binzi Cao
  • 1,075
  • 5
  • 14
  • This answer is great for answering why you can't assign null to a variable instantiated as Double. But in an answer I guess I was looking for the other half of the answer, how to deal with this situation in Scala. – cosmosa Apr 03 '17 at 01:04
0

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

mavarazy
  • 7,562
  • 1
  • 34
  • 60
  • if I set foo to None, I get "None.type doesn't conform to expected value Some[Double]". If I set it to null, it compiles. Now how do I retrieve the value from Some[Double]? If I do foo getOrElse(null) I get a nullPointerException. – cosmosa Apr 02 '17 at 14:03
  • try Option.empty[Double] – mavarazy Apr 02 '17 at 15:59
  • foo's type here is inferred to be `Some[Double]` which is not what you want because it doesn't allow for None. Yuo need to either add the type annotation `Option[Double]` or use `Option(0.0)` instead of `Some(0.0)`. foo also needs to be a var instead of a val here. – puhlen Apr 02 '17 at 22:33
  • This answer is incomplete and doesn't compile, as mentioned above – cosmosa Apr 03 '17 at 01:02