Scala Implicit Parameters and Classes

Question Click to View Answer

What does the following code print?

object Whatever {
  def speak(something: String)(implicit nice: String) = {
    println(s"$something $nice")
  }
}

println {
  Whatever.speak("I am ")("a surfer dude")
}

I am a surfer dude is printed.

nice is an implicit parameter that is set when the speak method is called.

Implicit parameters are similar to default parameters, but have some key differences.

What does the following code print?

object Whatever {
  def speak(something: String)(implicit nice: String) = {
    println(s"$something $nice")
  }
}

implicit val nice = "the walrus"
println {
  Whatever.speak("I am")
}

I am the walrus is printed.

The implicit value is set before the speak method is called, so it doesn't need to be passed in as an argument.

Setting implicit variables can potentially clean up code because the same variable doesn't need to be passed around all throughout the codebase.

But implicits are also dangerous because they can make a codebase a lot harder to follow. Users might not know where the implicit was set and what it's assigned to.

What does the following code print?

object Omg {
  def speak(implicit emotion: String) = {
    println(s"Pikachu is $emotion")
  }
}

implicit val abcdefg = "confused"

println(Omg.speak)

Pikachu is confused is printed.

You might be surprised to see that implicit emotion: String is using implicit val abcdefg = "confused".

When you call a method that takes an implicit value as an argument, the compiler searches for an implicit value that's been set with the same type.

In this case, the compiler searches for an implicit value with the String type.

It doesn't matter that the variable name abcdefg is different than the argument name emotion. All that matters is that an implicit String value exists.

What does the following code print?

object StringUtils {
  implicit class Better(val x: String) {
    def fun = {
      s"$x is fun!"
    }
  }
}

import StringUtils._
println("bob".fun)

bob is fun is printed.

Implicit classes let you add methods to existing objects. In this case, we're adding a method to the String object (which is a terrible idea).

Implicit classes should be defined in an object (in this case the implicit class is defined in the StringUtils object).

Implicit classes must take a single nonimplicit class argument (x is used in this example).

What does the following code print?

object IntUtils {
  implicit class Calculator(val num: Int) {
    def add(n: Int) = {
      num + n
    }
  }
}

import IntUtils._
println(4.add(5))

9 is printed.

The implicit class adds the add method to integers.

What does the following code print?

object DoubleUtils {
  implicit class Funny(val num: Double, joke: String) {
    def knockKnock = {
      s"${num.toString} is here"
    }
  }
}

import DoubleUtils._
println(3.14.knockKnock)

This code errors out because "implicit classes must accept exactly one primary constructor parameter". The joke parameter that was added to the Funny implicit class is causing the code to error out.

This code works.

object DoubleUtils {
  implicit class Funny(val num: Double) {
    def knockKnock = {
      s"${num.toString} is here"
    }
  }
}

import DoubleUtils._
println(3.14.knockKnock)

What does the following code print?

object Whatever {
  def speak(something: String)(implicit nice: String) = {
    println(s"$something $nice")
  }
}

implicit val nice = "the walrus"
println {
  Whatever.speak("I like")("catfood")
}

I like catfood is printed.

The implicit value is set, but it's overridden by the value that's explicitly passed when the speak method is called.

What does the following code print?

implicit val abcdefg = "confused"

def evil(implicit scared: String) = {
  println(s"Scala is $scared")
}

println(evil)
println(evil("cool"))

println(evil) prints Scala is confused.

println(evil("cool")) prints Scala is cool.

When we call these functions without arguments the compiler searches for a value for the function in the context of the method call. The compiler finds an implicit value for a string type and uses the string "confused". When a method is called with an argument, the argument value is used.

What does the following code print?

implicit val ones = 111
def coolNumber(implicit myNum: Int) = myNum
implicit val eights = 888
println(coolNumber)

The following error is returned.

error: ambiguous implicit values:
both value ones of type Int
and value eights of type Int
match expected type Int

The coolNumber function is looking for an implicit value with the Int type.

In this example, there are two implicit values with the Int type (ones and eights) and the compiler does not know which one to use. It throws an error because it doesn't know what implicit value to use.