Scala: Rolling with implicit
We’ve been coding in Scala on my project for around 6 weeks now and are getting to the stage where we’re probably becoming a big dangerous with our desire to try out some of the language features.
One that we’re trying out at the moment is the implicit key word which allows you to pass arguments to objects and methods without explicitly defining them in the parameter list.
The website we’re working on needs to be accessible in multiple languages and therefore we need to be able to translate some words before they get displayed on the page.
Most of the time it’s just static labels which need to be internationalised but there are a few words which are retrieved from the database and aren’t as easy to deal with.
We introduced the idea of the LanguageAwareString which acts as a wrapper around a String and has its own toString method which delegates to a Language class which contains a dictionary
It’s defined like this:
case class LanguageAwareString(ignorantValue:String)(implicit val language : Language) {
def toString = language.translate(ignorantValue)
}
We didn’t want to have to pass Language to the LanguageAwareString factory method every time we’re going to be calling it in quite a few places.
We therefore create an implicit val at the beginning of our application in the Scalatra entry code
class Controllers extends ScalatraFilter with ScalateSupport {
...
implicit def currentLanguage : Language = // work out the current language
}
As I understand it, whenever the Scala compiler encounters an implicit it looks in its execution scope for any value defined as implicit with the expected type.
As long as there’s only one such value in the scope it make use of that value but if there’s more than one we’d see a compilation error since it wouldn’t know which one to use.
We therefore needed to define Language as an implicit on all the classes/methods which the code follows on its way down to LanguageAwareStrong.
The problem we’ve had is that it’s not immediately obvious what’s going on to someone who hasn’t come across implicit before and we therefore end up having to go the above each time!
We’ve decided that to ease that transition we’d explicitly pass Language down through the first few classes so that it’s more obvious what’s going on.
We therefore have code like this in a few places:
new ObjectThatTakesLanguageImplicitly(someArg)(currentLanguage)
Maybe we can phase that out as people get used to implicit or maybe we’ll just get rid of implicit and decide it’s not worth the hassle!
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.