The following two code snippets are equivalent, differing only on what the client code ends up looking like, but yielding in all other ways similar results:
// --------------------
// In LibraryCode.scala...
package library.code;
// client code expected to import the following method and provide
// an implicit Thing value for t -- a "quiet-my-scope" patterned method.
def addedFeatureToSomeThing(implicit Thing t) = ...
// --------------------
// In ClientCode.scala...
import library.code._
// An implicit Thing value
implicit val someThing: Thing = ...
// Use of the someThing value as an implicit parameter to the library method
val result = addedFeatureToSomeThing
The code above can be refactored to the pimp-my-lib style which follows, and vice versa:
// --------------------
// In LibraryCode.scala
package library.code;
// client code expected to import the following implicit conversion method,
// which effectively adds a new method "addedFeature" to the Thing class in the importing scope.
implicit def convertThingToAddFeature(t: Thing) = new {
def addedFeature = ...
}
// --------------------
// In ClientCode.scala...
import library.code._
val someThing: Thing = ...
// Use of the pimp-my-lib-patterned convertThingToAddFeature implicit conversion method
val result = someThing.addedFeature
In both cases, the imported LibraryCode.scala provides a callable method which requires state in the form of a Thing object. I’m assuming the Thing type is also defined external to the client code — probably in a third-party library.
The first pattern, which to the best of my knowledge doesn’t have a name, you have a method in the local scope which accepts an implicit parameter, and effectively allows you to pass a single in-scope object to multiple methods without needing to repeat yourself. I’m going to dub this the “quiet-my-scope pattern“, because it reducesĀ the visual chatter that would otherwise be caused by passing the same object to multiple method calls — and I’ll just hope that name sticks.
The second is the famous pimp-my-lib pattern, which is well-known throughout Scalaland to be used to “add” methods to externally-defined classes.
Using implicits we have these two API patterns to choose from — they are equivalent, in so far as an implementation of either one can be mechanically transformed in to the other, only style and convenience being a differentiator between them. You might find it useful to keep around this alternative to the pimp-my-lib pattern, as in some APIs it will yield more readable, more convenient code.
Try it out: the next time you find yourself augmenting an existing class with methods using the pimp-my-lib pattern, take 5 minutes to refactor your solution to methods with implicit parameters (using the sample Thing code above as a guide). You won’t lose much time in the exercise, and you may find you’ll end up with better code.
Similarly, the next time you find yourself defining a method with an implicit parameter, take 5 minutes to work through what a refactored solution with a pimp-my-lib style method would look like. You may like the result quite a bit more than what you started with.
def addedFeatureToSomeThing(implicit Thing t) = …