Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala implicit object vs implicit val

Tags:

I've seen two ways (one less than the other) of declaring implicit for typeclass pattern in Scala.

implicit val instance1 = new Typeclass { def do = ??? }
implicit object instance2 extends Typeclass { def do = ??? }

How are they different? Should one prefer one to the other for certain times? I find implicit val much more commonly used than implicit object and I've yet to find many resources about implicit object.

like image 693
Daniel Shin Avatar asked Oct 24 '15 12:10

Daniel Shin


People also ask

What is implicit Val Scala?

Language. A method can have an implicit parameter list, marked by the implicit keyword at the start of the parameter list. If the parameters in that parameter list are not passed as usual, Scala will look if it can get an implicit value of the correct type, and if it can, pass it automatically.

How does Scala pass implicit value?

In simpler terms, if no value or parameter is passed to a method or function, then the compiler will look for implicit value and pass it further as the parameter. For example, changing an integer variable to a string variable can be done by a Scala compiler rather than calling it explicitly.

What is an implicit class in Scala?

An implicit class is a class marked with the implicit keyword. This keyword makes the class's primary constructor available for implicit conversions when the class is in scope. Implicit classes were proposed in SIP-13.

Where does Scala look for Implicits?

In this case, it looks inside the object Ordering , companion to the class Ordering , and finds an implicit Ordering[Int] there. This is how Scala found the implicit Numeric[Int] and Numeric[Long] in your question, by the way, as they are found inside Numeric , not Integral .


1 Answers

One difference is that the object version is going to be lazily initialized, i.e. it's constructor will not be called until the first time it is used. For example:

trait Incrementer[T] {
  def inc(x: T)
}

def increment[T](x: T)(implicit ev: Incrementer[T]) = ev.inc(x)

implicit object IntIncrementer extends Incrementer[Int] {
  println("IntIncrementer is being constructed...")

  def inc(x: Int) = x + 1
}

implicit val DoubleIncrementer extends Incrementer[Double] {
  println("DoubleIncrementer is being constructed...")

  def inc(x: Double) = x + 1D
}

Note that you will not see the message from IntIncrementer until it is used, e.g.

increment(1)  //this prints "IntIncrementer is being constructed..."

The message from DoubleIncrementer, however, will be displayed when it is defined. So the initialization of implicit object is lazy while the initialization of implicit val is strict.

like image 54
Jason Lenderman Avatar answered Sep 26 '22 13:09

Jason Lenderman