Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the Option's orNull method have this superfluous implicit argument?

I wonder what is the reason for the (implicit ev: Null <:< A1) here:

sealed abstract class Option[+A] extends Product with Serializable { 
  def orNull[A1 >: A](implicit ev: Null <:< A1): A1 = this getOrElse null
  ...
}

Wouldn't

def orNull[A]: A = this getOrElse null

be enough considering that it doesn't even seem to work with value types like

Option(1).orNull

but

Option(1).getOrElse(null)

does?

Option's source code

like image 466
soc Avatar asked Mar 15 '11 17:03

soc


2 Answers

Not all scala types can be null. In particular, Any has two children, AnyRef and AnyVal. AnyRef can handle null types. AnyVal types could be primitives on the JVM and therefore cannot be null. The implicit is a delayed type-check that allows Option[String] to use orNull but not Option[Int].

Note: This dichotomy of Int being boxed/unboxed object/primitive has very strange manifestations in Scala, such as null.asInstanceOf[Int] == 0 // true.

like image 128
jsuereth Avatar answered Oct 20 '22 01:10

jsuereth


scala> abstract class Op[A] {
     |   def getOrElse(b: A): A
     |   def orNull[A]: A = this getOrElse null
     | }
<console>:14: error: type mismatch;
 found   : Null(null)
 required: A
         def orNull[A]: A = this getOrElse null
                                           ^

So, null is not an acceptable type for all A, only for the nullable ones. The subclasses of AnyVal are typical examples of non-nullable types. In the absence of that parameter, it is not possible to write this method.

like image 42
Daniel C. Sobral Avatar answered Oct 20 '22 02:10

Daniel C. Sobral