Scala Tutorials Part #28 - Getting started with Implicits
Originally Posted On : 16 Dec 2017
Implicits
This is part 28 of the Scala tutorial series. Check here for the full series.
Index
- Introduction
- Implicit Variables & Method Parameters
- Implicit Functions
- Taking a look at the decompiled code
- Conclusion
Introduction
Implicit in the dictionary means predefined or understood. The implicit
keyword is extensively used in Scala and its important to understand its usage. If used correctly, they can greatly reduce the amount of boilerplate code.
Implicit Variables & Method Parameters
Let’s declare a method that takes in an implicit
parameter.
def multiply(implicit param1: Int) = param1 * value
value
is a variable which the multiply
method has scope to. So let’s just declare a simple variable as below.
val value = 10
We will be able to call the multiply
method without any parameters since one of them is implicit
and the other is global. But, it will lead to an error as we have not declared any implicit variables that is suitable for that method.
println(multiply)
Defining an implicit
variable fixes the error.
implicit val param1 = 2
Now,
println(multiply)
Will print 20.
An interesting thing to note here is that the implicit parameter can be of any name and the method would still work.
object RunExample extends App{
val value = 10
implicit val anotherValue = 2
def multiply(implicit param1: Int) = param1 * value
//Prints 20
println(multiply)
}
As you can see, only the variable type is more important rather than the name. At this point, an important question that would come up is what will happen if there are two implicit variables of the same type. Let’s test it out.
The compiler is much more strict here. It could resort to taking the first defined implicit value but it leads to bad/ambiguous code, so it promptly complains here.
Once we declare the first parameter as implicit, anything that follows it is also implicit. The below example makes it more clear.
def multiply(implicit param1: Int,param2 : Int) = param1 * param2
If we call just multiply
it prints 4 as it takes the value of anotherValue
twice. Usually there will be only one implicit parameter for a method. We cannot call param2
directly here since it is implicit.
It also not possible to make the second parameter implicit
. Such a syntax would lead to a compiler error.
Implicit Functions
Just like implicit method parameters, implicit functions are useful in places where we want the compiler to call the method automatically.
Let’s take the below example.
val x : Int = 20.23
This will obviously throw an error.
Let’s declare an implicit function that converts Double
to Int
.
implicit def doubleToInt(d: Double) = d.toInt
Now the the above code works as expected i.e it auto converts the Double
to Int
.
implicit def doubleToInt(d: Double) = d.toInt
val x : Int = 20.23
//Prints 20
println(x)
Very handy in situations where it needs this to be done by default
Taking a look at the decompiled code
The decompiled code for this is pretty simple.
public final void delayedEndpoint$com$testing$Runnable$1() {
this.value = 10;
this.anotherValue = 2;
.MODULE$.println(BoxesRunTime.boxToInteger(this.multiply(this.anotherValue())));
}
It directly replaces the references to the variables at compile time. If it seems confusing, the first thing is to look in the docs and take a look at the decompiled code.
Conclusion
Scala is not the first language to have this. C# has implicits which work very similar to Scala in terms of functionality and having a slightly different syntax. Scala libraries such as Akka make use implicits heavily. Many advanced patterns are possible with implicits
which I’ll cover in later tutorials.
This design pattern tends to be over used and should be used with caution. With power comes responsibility.