This is my first programming blog post. So please be gentle in your criticism. :-)

Emulating C#’s default keyword in Scala:

In generic classes and methods, one issue that arises is how to assign a default value to a type parameter A when you do not know in advance whether A is a reference type, a numeric type, or something else. To handle such a situation, C# provides a keyword default, which returns null for reference types, and zero for numeric types. For structs, which are CLR’s value types, default returns an object with all members initialized to their respective default values using the same mechanism.

Following example shows the default keyword in action:

using System;
using System.Diagnostics;
 
class Example {
  static void Main(string[] args) {
    Debug.Assert(default(Int32) == 0);
    Debug.Assert(default(Boolean) == false); 
    Debug.Assert(default(String) == null);
  }
}

Scala has a similar feature to get a default value for the given type parameter. Just declare a variable at the class level, annotate it with a type, and put an undescore after the assignment operator. The variable will then be assigned the appropriate default according to its type. (Note: All Scala snippets in this post are typed at REPL.)

scala> class Test[A] {
     |   var a: A = _
     | }
defined class Test

scala> new Test[Int].a
res3: Int = 0

scala> new Test[Boolean].a
res4: Boolean = false

scala> new Test[String].a
res5: String = null

However for some reason that I do not know of, this feature is only available for class fields. It doesn’t work for local variables.

scala> def default[A] = {
     |   var a: A = _
     |   a
     | }
<console>:8: error: local variables must be initialized
         var a: A = _
             ^

This can easily be work around:

scala> def default[A] = {
     |   class Test {
     |     var a: A = _
     |   }
     |   (new Test).a
     | }
default: [A]=> A

scala> default[Int]
res6: Int = 0

scala> default[Boolean]
res7: Boolean = false

scala> default[String]
res8: String = null

Thus we have successfully emulated the behavior of C#’s default keyword in Scala (Except for the structs’ case, which do not exist on JVM anyway).

Putting it on steroids:

Now what do I mean by putting default on steroids? Think how we could improve the behavior of the defaulting mechanism we built above. Wouldn’t it make more sense for a string to default to an empty string i.e. ""? Wouldn’t it make more sense for an Option[_] variable to default to None? Similarly your custom classes could have more appropriate defaults than null. For example, 0.0 + 0.0j would be a suitable default for a Complex object. In the remaining part of this post, we are going to see how Scala’s typeclasses let us build such a default-on-steroids.

Here is the required machinery for this little utility:

scala> :paste
// Entering paste mode (ctrl-D to finish)

trait Default[A] {
  def value: A
}

trait LowPriorityImplicitsForDefault { this: Default.type =>
  implicit def forAnyRef[A](implicit ev: Null <:< A) = Default withValue (null : A)
}

object Default extends LowPriorityImplicitsForDefault {
  def withValue[A](a: A) = new Default[A] {
    def value = a
  }

  implicit val forBoolean = Default withValue false
  implicit val forChar = Default withValue ' '
  implicit def forNumeric[A](implicit n: Numeric[A]) = Default withValue n.zero
  implicit val forString = Default withValue ""
  implicit def forOption[A] = Default withValue (None : Option[A])
}

// Exiting paste mode, now interpreting.

defined trait Default
defined trait LowPriorityImplicitsForDefault
defined module Default

The trait Default is a typeclass, which is invariant on A for obvious reasons. Its companion object Default contains implicits and implicit suppliers for a few common types. The method forAnyRef is put in a separate trait LowPriorityImplicitsForDefault so that it has a lower precedence than other more specific implicit supplier methods such as forNumeric (We do this to hack around Scala’s implicit lookup rules. Don’t bother if you do not understand this, as it’s beyond the point of this post).

Now all we need to do is define a no-arg method default that picks an appropriate Default implicit from the scope and returns its value.

scala> def default[A : Default] = implicitly[Default[A]].value
default: [A](implicit evidence$1: Default[A])A

And we are done! :-)

Here is our new default, in action:

scala> default[Int]
res0: Int = 0

scala> default[String]
res1: String = ""

scala> default[Boolean]
res2: Boolean = false

scala> default[Option[Int]]
res3: Option[Int] = None

Say, later on at some point we define a class Complex. How do you supply a Default implicit for it? Easy. Put it in Complex’s companion!

scala> :paste
// Entering paste mode (ctrl-D to finish)

case class Complex(real: Double, imaginary: Double)

object Complex {
  implicit val default = Default withValue Complex(0.0, 0.0)
}

// Exiting paste mode, now interpreting.

defined class Complex
defined module Complex

scala> default[Complex]
res6: Complex = Complex(0.0,0.0)

Cool, isn’t it? :-)

What happens when there’s no implicit defined for a certain type? Well, in such a case, the method forAnyRef acts as a fallback method, and default returns null.

scala> case class Point(x: Double, y: Double)
defined class Point

scala> default[Point]
res8: Point = null

This example shows how Scala’s typeclasses can be immensely useful in the cases requiring post hoc polymorphism.

Well, that’s it. I hope this was good enough an attempt for a first blog post. :-) All suggestions and criticism is welcome.