Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I obtain the default value for a type in Scala?

I'm trying to write a Scala function that returns the default value of a type (0, 0.0, false, '\0', etc. for value types and null for reference types). I came up with this:

def defaultValue[U]: U = {
  class Default[U] { var default: U = _ }
  new Default[U].default
}

and while this works well if called directly, it returns null even for value types when called through a function that itself is generic, as shown in this REPL session:

Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_24).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def defaultValue[U]: U = { class Default[U] {var default: U = _ }; new Default[U].default }
defaultValue: [U]U

scala> defaultValue[Boolean] // direct call works
res0: Boolean = false

scala> var res: Any = 0
res: Any = 0

scala> def setRes[U] = { res = defaultValue[U]; defaultValue[U] }
setRes: [U]U

scala> setRes[Boolean] // returns a Boolean, but...
res1: Boolean = false

scala> res
res2: Any = null // ... sets the res variable to null.

Can someone explain to me:

  1. why this happens (and why the compiler/interpreter doesn't complain if there is not enough information for it to return a true Boolean); and
  2. how I can fix it?
like image 708
Jean-Philippe Pellet Avatar asked Mar 10 '11 13:03

Jean-Philippe Pellet


People also ask

What is the default value for an object of type object?

Objects. Variables of any "Object" type (which includes all the classes you will write) have a default value of null. All member variables of a Newed object should be assigned a value by the objects constructor function.

How do I set default value in Scala?

You can assign a default value for a parameter using an equal to symbol. I gave a default value for the first parameter. If the caller doesn't pass any value for the first parameter, Scala will take the default value as println. That's it.

What is the default value for string data type?

The object and string types have a default value of null, representing a null reference that literally is one that does not refer to any object.


1 Answers

Here is a more condensed version of your issue:

scala> defaultValue[Boolean]: Any
res0: Any = null

scala> defaultValue[Boolean]: Boolean
res1: Boolean = false

The first version is what applies when you call res = defaultValue[U] because even though U is of type Boolean, res is of type Any

If you compile this little program using the -Xprint:all option

object Test {
  def defaultValue[U]: U = { class Default[U] {var default: U = _ }; new Default[U].default }

  def main(args:Array[String]) {
    val any = defaultValue[Boolean]: Any
    println(any)
    val bool = defaultValue[Boolean]: Boolean
    println(bool)
  }
}

You'll see that right before the erasure phase, you have:

val any: Any = (Test.this.defaultValue[Boolean](): Any);
scala.this.Predef.println(any);
val bool: Boolean = (Test.this.defaultValue[Boolean](): Boolean);
scala.this.Predef.println(bool)

Then at the end of the erasure phase:

val any: java.lang.Object = (Test.this.defaultValue(): java.lang.Object);
scala.this.Predef.println(any);
val bool: Boolean = (scala.Boolean.unbox(Test.this.defaultValue()): Boolean);
scala.this.Predef.println(scala.Boolean.box(bool))

So what happens is that under the hood defaultValue[Boolean] returns null in both cases, but then null is unboxed into false when the return type is a Boolean. You can verify that in the REPL:

scala> Boolean.unbox(null)
res0: Boolean = false

scala> null.asInstanceOf[Boolean]
res1: Boolean = false

Edit: I had an idea - not that I'm recommending it. Not sure what your use case is (res = false seems easier to me..)

scala> def f[@specialized U] = { class X { var x: U = _ }; (new X).x }
f: [U]U

scala> var res: Any = _
res: Any = null

scala> def g[@specialized U] = { res = f[U]; f[U] }
g: [U]U

scala> g[Boolean]
res0: Boolean = false

scala> res
res1: Any = false
like image 110
huynhjl Avatar answered Oct 14 '22 18:10

huynhjl