How to keep your sanity working with Scala Implicit!
Courtesy: https://www.pexels.com/
Intro
Scala Implicits provide a lot of power and flexibility to express the code in such beautiful ways that development sometimes feel like and art and are nothing short of a “Brahmastra” in the hand of a library developer.
And, as Spider-man’s uncle said,
“With great power, comes greater responsibility!”
The abuse of such a powerful feature has made working with them a nightmare sometimes for the end users. For example:
You will keep you head scratching over the above script until you find an implicit conversion (from Int to String) and an extension method (toHindiDigits) coming from just two imports!
Even Martin Odersky ( 🙌), the creator of Scala has admitted that he has made quite a few mistakes with the Implicits while designing the Scala language 😱!
While this can be really disheartening, this is not enough of a reason to move away from an amazing programming language, just because of a really abused feature! After all, there are other languages with much more horrible warts!
Courtesy: https://me.me
And JS is the most popular language right now 😉So, coming onto our topic, keeping the sanity of our mind! For that, we can follow some tips:
Use an IDE
Personal choice, IntelliJ IDEA with Scala plugin.
Look at features from JetBrain’s Scala plugin blog:
You can show implicitly passed parameters in a function, using “show implicit hints” feature, so that there’ll be no surprises as what was passed:
Similar example,
Avoid implicit conversions/defs
This can become a complete nightmare if a String or any type gets converted to another on the fly without even telling us and we spend hours debugging the issue
Even Scala compiler will warn you if you use implicit conversion without a specific import ( scala.language.implicitConversions ):
So, the tip is, avoid implicit conversions at all costs. When you absolutely need a conversion in your code in a convenient manner, please use implicit classes with extension method like:
trait A
trait B
//avoid this:
//implicit def aToB(a: A): B = ???
//do this instead:
implicit class RichA(a: A) {
def toB = ???
}
//use it like this:
val someA: A = ???
val someB: SomeB = someA.toB
//so that, this will be avoided:
//val someB: SomeB = someA
Ditch the type inference and annotate the required types
Simple logic: Avoid surprises 😅 and let compilation fail on mismatches!
Check the imports
Any underscore imports may contain implicit conversions, parameters and/or somewhat safe implicit classes.
Conclusion
So, these were my highly opinionated rules to avoid surprises and headaches while working with Scala Implicit! They are really powerful tools for writing really awesome code, please use them, don’t abuse them :)