Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Caching implicit resolution

To reduce compile times of my project, I'm caching certain type classes that are resolved by implicit lookups. This appears somewhat cumbersome though, because the straight forward implementation does not work:

scala> implicit val x: String = implicitly[String]
x: String = null

The implicit lookup considers its own, uninitialized definition as a valid implementation. A lazy val would blow the stack with infinite recursion. Therefore I'm currently handling it in this fashion:

implicit val x: String = cache.x

object cache {
   val x: String = implicitly[String]
}

But this makes it overly complicated, and the cache-definitions can not make use of other cached type classes easily (since they are not implicit).

Also, hiding the value itself from scope does unfortunately not work.

scala> :pas
// Entering paste mode (ctrl-D to finish)

object scope {
    implicit val x: String = {
        import scope.{ x => _ }
        implicitly[String]
    }
}

// Exiting paste mode, now interpreting.

defined object scope

scala> scope.x
res0: String = null

Is there a more elegant way to achieve an implicit resolution cache?

like image 451
Taig Avatar asked Dec 21 '15 15:12

Taig


2 Answers

Shapeless provides a cachedImplicit macro with an implementation that's very similar to yours (it uses shadowing to avoid the recursion, and the fact that it's a macro means the usage can be cleaner).

There are some limitations to be aware of, and you may not want to take on a new dependency for this single method, but the implementation is pretty concise, and it's at least a good starting point.

like image 127
Travis Brown Avatar answered Oct 18 '22 16:10

Travis Brown


Just for the sake of completeness: the shapeless macro in the accepted answer shadows its own definition in a way I didn't come up with. My particular problem could therefore be solved this way:

implicit val x: String = {
    def x = ???
    implicitly[String]
}
like image 29
Taig Avatar answered Oct 18 '22 16:10

Taig