Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save fpopic/2feaba4bac3f3b34e47156bc8db89176 to your computer and use it in GitHub Desktop.

Select an option

Save fpopic/2feaba4bac3f3b34e47156bc8db89176 to your computer and use it in GitHub Desktop.
//1. no tag List[T] becomes List at runtime so first case will always work
object Main {
def f[T](l: List[T]): Unit = {
l match {
case f: List[Float] => println("Floats: " + f)
case s: List[String] => println("Strings: " + s)
case i: List[Int] => println("Integers: " + i)
// case p: Int if classTag[T] == classTag[Int] => println("Int: " + p)
case _ => println("error")
}
}
def main(args: Array[String]): Unit = {
f(List(1, 2, 3)) //floats
f(List("a", "b")) //floats
// f(1)
}
}
//2. added T:ClassTag becomes List at runtime so first case will always work because we didn't check tag
object Main {
def f[T](l: List[T]): Unit = {
l match {
case f: List[Float] => println("Floats: " + f)
case s: List[String] => println("Strings: " + s)
case i: List[Int] => println("Integers: " + i)
// case p: Int if classTag[T] == classTag[Int] => println("Int: " + p)
case _ => println("error")
}
}
def main(args: Array[String]): Unit = {
f(List(1, 2, 3)) //floats
f(List("a", "b")) //floats
// f(1)
}
}
// 3. we add classTag[T] checks it works as expected, but we got warning
// Warning:(9, 15) non-variable type argument Float in type pattern List[Float] (the underlying of List[Float]) is unchecked since it is eliminated by erasure
case f: List[Float] if classTag[T] == classTag[Float] => println("Floats: " + f)
...
object Main {
import scala.reflect.{ClassTag, classTag}
def f[T: ClassTag](l: List[T]): Unit = {
l match {
case f: List[Float] if classTag[T] == classTag[Float] => println("Floats: " + f)
case s: List[String] if classTag[T] == classTag[String] => println("Strings: " + s)
case i: List[Int] if classTag[T] == classTag[Int] => println("Ints: " + i)
// case p: Int if classTag[T] == classTag[Int] => println("Int: " + p)
case _ => println("error")
}
}
def main(args: Array[String]): Unit = {
f(List(1, 2, 3))
f(List("a", "b"))
// f(1)
}
}
// 4. we can add @unchecked to mute warnings
import scala.reflect.{ClassTag, classTag}
object Main {
// ClassTag are enough to pattern match top-level class type
// doesn't know about every field's type, no reflection (no class mirror is build)
// TypeTag use reflection (build full mirror)
def f[T: ClassTag](l: List[T]): Unit = {
l match {
case f: List[Float@unchecked] if classTag[T] == classTag[Float] => println("Floats: " + f)
case s: List[String@unchecked] if classTag[T] == classTag[String] => println("Strings: " + s)
case i: List[Int@unchecked] if classTag[T] == classTag[Int] => println("Ints: " + i)
// case p: Int if classTag[T] == classTag[Int] => println("Int: " + p)
case _ => println("error")
}
}
def main(args: Array[String]): Unit = {
f(List(1, 2, 3))
f(List("a", "b"))
// f(1)
}
}
// 5. else we have to check element by element or use reflection (TypeTags)
def f[T: ClassTag](l: T): Unit = {
l match {
// Seq[Any] will be matched to this case because of type erasure,
// ok only if Seq[TableRow] is possible otherwise whill get runtimeException will handling elements
case nestedRepeated: Seq[TableRow@unchecked] if classTag[T] == classTag[TableRow] => println("TableRows: " + nestedRepeated)
case nested: TableRow if classTag[T] == classTag[TableRow] => println("Int: " + nested)
case _ => println("error")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment