Scala Implicits Part 1
Scala Implicits Part 1
This article is for those who start learning Scala and need a first-look to the implicits as well for those who despite not using Scala want to know what “implicits” are about.
Join the DZone community and get the full member experience.Join For Free
This article is not going to be an in-depth look at implicits in Scala. Instead, it will be about what they are. This article is for those who are starting to learn Scala and need a first-look at implicits as well for those who, despite not using Scala, want to know what “implicits” are all about.
This will be a series of articles, this being the first (and serving as an index for the upcoming ones) and continuing with more detailed and in-depth articles on Scala implicits — their operation and their use.
So, let’s start:
What Does Implicit and Explicit Mean?
These two words are used very often when we speak about Scala implicits (oh, well, I did not expect it) and like almost everything in the world of programming, they are borrowed from other aspects of our lives.
The Dictionary Definition Is the Following:
- implicit, ta Del lat. implicĭtus.
adj Included in something else without expressing it.
- Explicit, ta Del lat. explicĭtus.
adj That expresses one thing clearly and determinedly.
But let’s look at an everyday example. When we speak with each other, we do not explicitly mention everything we talk about, but there are many things that are understood by context.
If, for example, we are going to go out on a motorcycle and I ask you to give me the helmet, you will give me my helmet, however, I have not explicitly said that it is that helmet. You have understood it by context, that when I asked for the helmet I was referring to mine; it was implicit.
In fact, it is weird to mention explicitly everything that we refer to *(except a purely technical context in which precise instructions are given)*.
And in Code?
Okay, but what does it have to do with programming?
Well, Scala has a concept that is similar to the one we just described.
What would happen if we did not have to explicitly pass parameters to a function? If the function understood them by context? Or if we did not have to call a function explicitly and the compiler understood that by the context in which we are? Would we want to use it? That’s the concept, everything is in the context, and there are different ways in which Scala has implemented the concept of implicits.
What Types of Scala Implicits Are There?
The methods in Scala can receive a last list of parameters, with the prefix implicit.
This list of parameters can be called normally if you want to:
But its main characteristic is that you can define an implicit value/function/definition in your code, and if it is in the same context… the compiler will use it!
However, if the compiler does not find any implicit value with the indicated type … it will fail:
This allows to eliminate code duplication in calls to different methods that require the same parameter as well as inject collaborators to components (Dependency Injection).
Implicit Conversions (Implicit Functions)
What happens when a method requires a type A, and you want to pass it a value of type B? What happens when a method returns a type C and you want a type D? The answer to both questions is the same: Either ask someone to change the signature and the implementation … or you’ll change function A => B to fix the problem.
The “problem” is that you will have to apply this function in all the places where you need it, which implies some duplication of code. Moreover, we have to modify our code to add this transformation. And if we are using generics? We could not know what converter to use … maybe using pattern matching …
This is one of those cases. The compiler complains about createNumber because it returns Int and not String. We are going to create an implicit conversion to do the transformation automatically:
The power of this tool has few limits and has some practical uses, such as defining the transformation of a DTO to domain (or vice versa) in an implicit conversion.
The parameters and the implicit transformations are the best known, but there are more types, such as implicit classes.
What do you think this piece of code does? The answer is easy (and many will say, aaaah okay) extension methods
Like all implicits, it has its limitations, but also a lot of utility: How would you add additional behavior to a class, which could or could not be yours? Composition or inheritance, right? And if it is the last one and you can not extend it? You have a composition, and that can mean making a wrapper, etc.
Like this we can work with Author in a natural way.
This is the most used form of implicit, and at the same time the least used by itself. It allows us to create and use typeclasses, which are widely used both in the stdlib and in other libraries. However, their use besides aside from typeclasses is practically non-existent. An implicit object is one that the compiler can deliver when an implicit parameter of the same type as that object is requested. It’s like an implicit parameter for objects to understand each other.
You may think, that you don’t see a lot of use cases. Well, later you will see what you can get by using these implicit objects.
What Problems Do They Have?
Implicits are a very powerful tool. You may want to abuse them once you start discovering them. And that’s not good — believe me, I’ve lived it. Code in which the implicits are abused is one of the most difficult things to understand, follow, and debug that you can find.
Everything is magic (black magic in many cases). Things happen and at first sight, you have no control over anything. It is possible that you leave an implicit to declare and that everything compiles because someone has declared an implicit value in that scope and the types match. Debugging that is criminal.
Ambiguous Implicit Definition
Implicit are looked for based on the required type. That means that we cannot have two implicits with the same type within the same scope. The compiler would not know what to do!
Although you want to use them for different things, if they have the same type, you cannot have two implicits sharing the same scope. Which brings us to a conclusion: we need to be careful with Primitive Obsession. If we type in a specific way, with specific types and not with primitives, we can avoid this type of problem.
Final Words: Scala Implicits
Summing up, we eliminate boilerplate with the implicits. We write much less code and we solve everything in compilation — nevertheless everything is not perfect. Code sometimes can be impossible to understand (The authors of Kotlin have taken the specific decision not to implement them in the language).
We could say: “you have to use them in moderation”, but for us, the question is not so much about moderation or not, but the criteria and the patterns of how and when to use them since this is an architectural decision.
At the end of this series, we will mention some criteria examples.
Recommended Readings on Implicits
If you want a light reading on implicits, you can read the upcoming chapter in which we will talk about patterns with Scala implicits, how the compiler looks for them and examples found in the stdlib and in bookstores like scalaz. Also, you can read these recommendations:
- Scala in action: capítulo 8.3
- Scala by example: capítulo 15
- Solo para valientes: https://www.artima.com/pins1ed/implicit-conversions-and-parameters.html
Published at DZone with permission of Rafael Ruiz Giner . See the original article here.
Opinions expressed by DZone contributors are their own.