2015-12-21 10 views
9

Um die Kompilierzeiten meines Projekts zu reduzieren, speichere ich bestimmte Typklassen, die durch implizite Suchvorgänge aufgelöst werden. Dies scheint zwar etwas umständlich, weil die gerade nach vorne Umsetzung nicht funktioniert:Caching implizite Auflösung

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

Die implizite Lookup seine eigene, nicht initialisierte Definition als gültige Implementierung berücksichtigt. Ein lazy val würde den Stapel mit unendlicher Rekursion blasen. Deshalb bin Umgang ich es zur Zeit in dieser Art und Weise:

implicit val x: String = cache.x 

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

Aber das macht es zu kompliziert, und die Cache-Definitionen können nicht ohne weitere Verwendung anderer Cache gespeicherten Typklassen machen (da sie nicht implizit sind).

Auch das Verbergen des Wertes selbst aus dem Bereich funktioniert leider nicht.

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 

Gibt es eine elegantere Möglichkeit, einen impliziten Auflösungscache zu erreichen?

+1

@Taig Haben Sie Shapeless '' cachedImplicit' Makro betrachtet? Es ist [sehr ähnlich] (https://github.com/milessabin/shapeless/blob/dee18017c0c0284cde270948a16382ffc1f41273/core/src/main/scala/shapeless/package.scala#L126) was du tust. –

+0

@TravisBrown das ist genau * was ich gesucht habe (und insgeheim gehofft habe). Ich habe es bei meinen Google-Abfragen nicht gefunden. Wenn Sie Ihren Kommentar in eine Antwort verschieben, nehme ich gerne an. – Taig

Antwort

9

Shapeless ein cachedImplicit Makro mit an implementation, die Ihnen sehr ähnlich ist (es verwendet Shadowing die Rekursion zu vermeiden, und die Tatsache, dass es ein Makro bedeutet die Verwendung sauberer sein können).

Es gibt some limitations zu beachten, und Sie möchten möglicherweise nicht eine neue Abhängigkeit für diese einzelne Methode übernehmen, aber die Implementierung ist ziemlich knapp, und es ist zumindest ein guter Ausgangspunkt.

3

Nur der Vollständigkeit halber: das formlose Makro in der akzeptierten Antwort beschattet seine eigene Definition in einer Weise, die ich nicht gefunden habe. Mein spezielles Problem könnte daher auf diese Weise gelöst werden:

implicit val x: String = { 
    def x = ??? 
    implicitly[String] 
}