Skip to content

Instantly share code, notes, and snippets.

@asieira
Last active December 29, 2016 20:11
Show Gist options
  • Save asieira/274a9e72a6ed11eb1335f9d5f6af7fee to your computer and use it in GitHub Desktop.
Save asieira/274a9e72a6ed11eb1335f9d5f6af7fee to your computer and use it in GitHub Desktop.
Generic implementation of instance interning (de-duplication) in Scala
// This trait defines the mechanism by which the global repository (pool) of objects
// is obtained for each type.
trait Interning[T] {
def repository: java.util.Map[T, T]
def intern(orig: T): T = {
val retval = repository.putIfAbsent(orig, orig)
if (retval == null) orig
else retval
}
}
object Interning {
// Handy implementation that creates a synchronized weak hash map for a type.
def repository[T]: java.util.Map[T, T] =
java.util.Collections.synchronizedMap[T, T](new java.util.WeakHashMap[T, T])
// Convenience method to allow types that don't extend Internable to be interned.
def apply[T : Interning](orig : T) = implicitly[Interning[T]].intern(orig)
}
// This is supposed to be used as a mixin for classes that will support interning.
trait Internable[T] {
def intern(implicit interning: Interning[T]): T = interning.intern(this.asInstanceOf[T])
}
// Example usage with a test class
case class Test(a: String) extends Internable[Test]
implicit object InterningTest extends Interning[Test] {
// it's critical to use a val and not a def here so that all Test instances
// are using the same repository for interning
override val repository = Interning.repository[Test]
}
// We can also use this with an existing type such as List[Int]
implicit object InterningListInt extends Interning[List[Int]] {
override val repository = Interning.repository[List[Int]]
}
object main {
def main(args: Array[String]) = {
// interning our own class
val a1 = new Test("a")
val a2 = new Test("a")
println(a1 eq a2) // False
println(a1.intern eq a2.intern) // True
// interning List[Int]
val l1 = List(1, 2, 3)
val l2 = List(1, 2, 3)
println(l1 eq l2) // False
println(Interning(l1) eq Interning(l2)) // True
}
}
@asieira
Copy link
Author

asieira commented Dec 29, 2016

An exercise in Scala features such as implicits and traits. The idea here was to try to generalize what String.intern does for any class in Scala.

The use of asInstanceOf in Internable is a risk, but I couldn't find a better way of making this work while still keeping the return type of the intern method equal to T. Suggestions on a better approach are most welcome.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment