In the code below there are 2 case classes Person and Employee. There is a function called
emp which takes in an Employee and returns a string. Instead I pass a person while defining an implicit def for converting a Person to Employee.
case class Person(fName : String, lName : String, dob : Date, gender : String)
case class Employee(fName : String, lName : String, dob : Date, gender : String, department : String)
implicit def toEmployee(person : Person) : Employee = Employee(fName = person.fName, lName = person.lName,
dob = person.dob, gender = person.gender, department = "Fire Squad")
val aPerson = Person(fName = "John", lName = "Doe", gender = "Male", dob = new Date())
def emp(employee: Employee) : String = ???
But was this the actual purpose for the introduction of implicits? Or was it to support type classes? If it was to support type classes should the above code be changed to introduce an adh-hoc method called
toEmployee for the class
Person. And then
emp can be called using
Which the correct way to use implicits ?
Without answering your question of original intent, i’ll say:
Implicit conversions like this are often hard to reason about, especially when the conversion itself (
toEmployee) is being defined in an ad hoc fashion away from the definition of either
Employee. In fact, dotty might end up disallowing that case, if i recall correctly.
If that’s what’s actually happening in your non-example code, then you’re probably better off with an explicit conversion.
The original purpose of introducing implicit parameters is not necessarily an indicator for what usage is considered good code. You can even see this in the standard library: the JavaConversions object provides implicit conversions between Java and Scala collections, similar to your usage, so such conversions may very well have been one of the intentions. But that class is now deprecated in favor of Java Converters:
The transparent conversions provided here are considered fragile because they can result in unexpected behavior and performance.
Therefore, this API has been deprecated and
JavaConverters should be used instead.
JavaConverters provides the same conversions, but through extension methods.
So, independently of original intentions, explicit conversion via methods is considered better style. Implicit conversions are used for providing such methods for types over which one does not have control, but these are considered better, as they usually use a wrapper that would not be used directly anywhere, so the conversion would only be triggered on method lookup of the extension method.
Thanks a lot. Makes sense. Btw, can you point me to the SIP where they talk about disallowing such a case in dotty?
I haven’t seen a SIP and given that it’s dotty not scala 2.x i’m not sure one exists (nor does 30 seconds of googling find it for me).
He’s spoken a lot about it in his recent conference keynotes (example: slide ~26 of https://www.slideshare.net/Odersky/preparing-for-scala-3)
There’s also this, which was an early attempt to implement the change in dotty: https://github.com/lampepfl/dotty/pull/2060
It’s a bit hard to talk about “the original purpose” of implicits – it was a long time ago, and in practice they are used for many different use cases now. Martin might remember what he originally intended, but I’ve never heard the reasoning.
To your question about Dotty: implicits are probably changing dramatically in Dotty. While nothing is final yet, it looks like the all-purpose keyword “implicit” is being replaced by a bunch of special-purpose syntax and functionality; the theory is that these will be easier to reason about than the current situation, less ambiguous, and a bit easier to teach.
In this specific case, it’s being replaced by “implicit conversions” – you can find the documentation here. More generally, the whole documentation section on “Contextual Abstractions” discussions the functionality that is implicit-like in Dotty; if you’re interested in where things are likely going, the Dotty documentation is fascinating. (Again, none of this is final, but it’s the current state of thinking.)
All that said – I would agree with the above commentators to be cautious about this sort of silent implicit conversion. It’s easy to casually abuse these conversions, and they can make the code more cryptic – they’re sometimes a huge help, but most often don’t really add much. Personally, I think your typeclass approach is usually clearer and more appropriate.