Let’s talk about Implicit

Reading Time: 6 minutes
Implicit use case

I hope from the above picture you can get an idea of “how an implicit can be useful”. This is just a single use case and if you are more interested in knowing about Implicit then this blog is for you. In this blog, I am going to discuss Implicit in Scala. I hope this will be useful to you. So, let’s talk about implicit

What is Implicit?

The literal meaning of implicit is “Something that is suggested or implied”. We can see it as something that is not directly or that someone understands themselves. In Scala also, the implicit has pretty much similar meaning. Before going in much detail, I’ll take a simple example and explain how the compiler implements it.

Example

Error without implicit

So here we can see that the variable number has a type Int but the value assigned to it is 3.5 i.e a Double. As expected, it shows a type mismatch problem. So how can we resolve it? What can be the alternative to making it right without actually providing it with an integer value? For that, we can do the following:

Implicit example

We are using a function “doubleToInt” that will convert a value of type Double to Int. But why we are not facing the type mismatch problem now? We are not doing any conversion ourselves by using the function then also now the value of the number is converted to Int i.e 3 instead of 3.5. How this is possible? All this is happening because the function “doubleToInt” is Implicit. Scala compiler will look for any implicit in the scope that it can use to resolve the type mismatch problem that we have seen before. Here it finds the function “doubleToInt” and now it’s the duty of Scala compiler to insert the implicit function at the right place and use it for the conversion itself.

Rules for Implicit

Marking rule: Only definitions marked implicit are available.

This rule simply says that compiler will only look at the functions, variables or object definition that are marked as implicit.

It will help in avoiding the confusion for the compiler if it was picking the functions randomly.

Scope rule: An inserted implicit conversion must be in scope as a single identifier, or be associated with the source or target type of the conversion.

This rule simply says that the implicit conversion should be in scope. In scope means that either it should be in the same class or object. If the conversion is in companion object then also it is good to go. Also, the implicit conversion can be associated with source type or target type. Now, what does the source type or target type mean? Consider you are passing Rupee in a function that requires Dollar. In this Rupee is source type and Dollar is target type. If we have an implicit conversion in source’s or target’s companion object then it is good to go. This is what we mean by associated here.

An example of implicit

Also, we can see that the implicit conversion should be as a single identifier. This means that the compiler will not insert a conversion of form object-name.convert rather we will have to import it. By importing the compiler can use the object-name.convert as convert which makes it a single identifier.

One-at-a-time rule: Only one implicit is inserted.

This rule simply says that compiler will insert one implicit a time. Also, it won’t insert another implicit if it is already in the middle of trying another implicit. And this actually makes sense. If the Scala compiler inserts and try all the implicit available at once it will increase compiler time.

Explicit-first rule: Whenever code type checks as it is written, no implicit are attempted.

This says the compiler will not insert an implicit if the code already works. If we are doing a conversion explicitly or providing the parameter then the compiler won’t look for an implicit. This actually saves compiler time. This also indicates that by doing things our self in the code and using less implicit will take less compiler time and also reduce the ambiguity.

Implicit Parameters

A parameter in a class constructor or a function definition can be marked implicit. By marking a parameter implicit we need not pass it explicitly. We just need to declare the implicit variable and the Scala compiler will insert it automatically. Let me show you this by an example.

Implicit parameter example

Output will be:

output

In this, we are not passing the parameter. The compiler will look for an implicit of type String in the scope and insert it.

Note: The above example is not a good use case. If there is more than one implicit variable of type String then it will show an error.

Implicit parameter
Error when multiple implicit variable of same type are in scope

A good use case for use of Implicit parameter will be to provide some parameters that will have the same value and are used multiple times. For example, providing an Actor System and Materializer in Akka-Streams.

Implicit Classes

An implicit class has an implicit keyword with it. When we make a class implicit, the compiler generates an implicit function for it. This function basically takes the constructor variable as a parameter and creates an instance of the class.

By making a class implicit all its function can be used by the constructor variable. Let me show you how.

Implicit class

As class Palindrome is implicit an implicit function is automatically generated for it. Such as :

//Automatically generated
implicit def Palindrome(str:String) = new Palindrome(str)

Because we get this implicit method we are able to call the function isPalindrome by using a string. What actually happens is, the compiler gets a string but to use isPalindrome function it needs an instance of Palindrome. So it searches for an implicit function that will convert string to Palindrome. Then it finds the automatically generated implicit function. And that’s how all this is possible.

Advantage of making a class implicit is that we can make pre-defined types rich.

One thing to take care is the implicit class can only have single parameter and so it’s not possible to make every class implicit.

Implicit Functions

The implicit functions are those that are marked implicit and are mainly used for the type conversion. The example that I have discussed above of “doubletoInt” function or “rupeeToDollar” function are an example of implicit function.

Disadvantage of Implicit

  • Lot’s of implicit can create ambiguity for the compiler.
  • Many implicit can lead to more compiler time.
  • Also sometimes if a person does not have good knowledge about how implicit work, he/she can face problems in debugging code.

That’s all from my side. I hope it was helpful.

Reference


Knoldus-blog-footer-image