Skip to content

Instantly share code, notes, and snippets.

@kumarishan
Last active August 29, 2015 14:21
Show Gist options
  • Save kumarishan/f38fec3778fa92c55a07 to your computer and use it in GitHub Desktop.
Save kumarishan/f38fec3778fa92c55a07 to your computer and use it in GitHub Desktop.

Revisions

  1. kumarishan revised this gist May 18, 2015. 1 changed file with 53 additions and 2 deletions.
    55 changes: 53 additions & 2 deletions Example1.scala
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@ case class A(a: Int)
    case class B[T](b: T)

    object Example1 {

    // [IMP] the names of vals has to be capital case
    // so that they can be used in case statement.
    // case statement requires stable identifiers and therefore
    @@ -50,7 +50,15 @@ object Example1 {
    }


    def main(args: Array[String]) {
    def fromString(s: String): Class[_] =
    s match {
    case "a" => classOf[A]
    case "b" => classOf[B[Any]]
    case "string" => classOf[String]
    case "list" => classOf[List[Any]]
    }

    def helo(args: Array[String]) {

    println(foo(classOf[String])) // output -> it's String
    println(foo(classOf[B[Int]])) // output -> it's B
    @@ -89,6 +97,49 @@ object Example1 {
    // Therefore as long as only erased type infomation
    // is needed to match and perform action. Then classOf
    // or better yet ClassTag is the best way to do

    // classOf vs ClassTag route
    // Now what if you had a string and using that you
    // want to retriev the type to be used and to call
    // other classes that take action baed on type parameter

    // First using classOf based methods
    // This function takes a string, gets Class[_]
    // object and passes it to foo
    def aloha1(s: String) = {
    val clazz = fromString(s)
    foo(clazz)
    }


    // But if u wanted to user the fooBetter, i.e
    // which uses the ClassTag on T type parameter
    // same thing can be done like this
    def aloha2(s: String) = {
    implicit val tag = ClassTag(fromString(s)) // here tag's type is ClassTag[Nothing]
    fooBetter // this will automatically take the above implicit val
    }

    // Well from first glance aloha1 appears to simple and faster.
    // So lets check it.

    val ps = Array("a", "b", "string", "list")

    val itr = 1000000
    val params = Array.fill(itr)(ps(Random.nextInt(4)))

    var startTime = System.currentTimeMillis
    for(i <- 0 until itr) aloha1(params(i))
    println(s"Finished in ${System.currentTimeMillis - startTime}")

    startTime = System.currentTimeMillis
    for(i <- 0 until itr) aloha2(params(i))
    println(s"Finished in ${System.currentTimeMillis - startTime}")

    // The results of the above run proves that classOf way is more
    // perfomant but its not really much big of a difference like 10 milliseconds
    // in the above run

    }

    }
  2. kumarishan revised this gist May 18, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Example1.scala
    Original file line number Diff line number Diff line change
    @@ -88,7 +88,7 @@ object Example1 {

    // Therefore as long as only erased type infomation
    // is needed to match and perform action. Then classOf
    // or better ClassTag is best option
    // or better yet ClassTag is the best way to do
    }

    }
  3. kumarishan revised this gist May 18, 2015. 1 changed file with 5 additions and 4 deletions.
    9 changes: 5 additions & 4 deletions Example1.scala
    Original file line number Diff line number Diff line change
    @@ -57,11 +57,12 @@ object Example1 {
    println(foo(classOf[A])) // output -> it's A
    println(foo(classOf[List[String]])) // output -> it's list

    // This still gives "it's B" even though we used
    // BClass which used classOf[B[Int]]. This happens
    // because T of B[T] is erased by the compiler
    // If you passed classOf[B[String]] this will
    // still give "it's B" even though we used
    // BClass which is classOf[B[Int]].
    // This happens because T of B[T] is erased by the compiler
    // and classOf only represent the erased or runtime
    // type
    // type i.e. B
    println(foo(classOf[B[String]])) // output -> it's B

    // you call also verify like this
  4. kumarishan revised this gist May 18, 2015. 1 changed file with 6 additions and 1 deletion.
    7 changes: 6 additions & 1 deletion Example1.scala
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,12 @@ case class A(a: Int)
    case class B[T](b: T)

    object Example1 {


    // [IMP] the names of vals has to be capital case
    // so that they can be used in case statement.
    // case statement requires stable identifiers and therefore
    // in order to match, classOf[String] cannot be directly
    // used.
    val AClass = classOf[A]
    val StringClass = classOf[String]
    val BClass = classOf[B[Int]]
  5. kumarishan created this gist May 18, 2015.
    88 changes: 88 additions & 0 deletions Example1.scala
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,88 @@
    import scala.reflect._

    case class A(a: Int)
    case class B[T](b: T)

    object Example1 {

    val AClass = classOf[A]
    val StringClass = classOf[String]
    val BClass = classOf[B[Int]]
    val ListClass = classOf[List[String]]


    def foo(clazz: Class[_]) =
    clazz match {
    case AClass => "it's A"
    case BClass => "it's B"
    case StringClass => "it's String"
    case ListClass => "it's list"
    }


    def fooBetter[T: ClassTag] =
    implicitly[ClassTag[T]].runtimeClass match {
    case AClass => "it's A"
    case BClass => "it's B"
    case StringClass => "it's String"
    case ListClass => "it's list"
    }

    def bar[T: ClassTag](a: Int) =
    implicitly[ClassTag[T]].runtimeClass match {
    case AClass => s"it's A and $a"
    case BClass => s"it's B and $a"
    case StringClass => s"it's String and $a"
    case ListClass => s"it's list and $a"
    }

    def notSoGoodBar(a: Int, clazz: Class[_]) =
    clazz match {
    case AClass => s"it's A and $a"
    case BClass => s"it's B and $a"
    case StringClass => s"it's String and $a"
    case ListClass => s"it's list and $a"
    }


    def main(args: Array[String]) {

    println(foo(classOf[String])) // output -> it's String
    println(foo(classOf[B[Int]])) // output -> it's B
    println(foo(classOf[A])) // output -> it's A
    println(foo(classOf[List[String]])) // output -> it's list

    // This still gives "it's B" even though we used
    // BClass which used classOf[B[Int]]. This happens
    // because T of B[T] is erased by the compiler
    // and classOf only represent the erased or runtime
    // type
    println(foo(classOf[B[String]])) // output -> it's B

    // you call also verify like this
    println(classOf[B[String]] eq classOf[B[Int]]) // output -> true

    // Now fooBetter makes the above code even more prettier
    // by using ClassTag.
    // This allows us to pass only the type in Type Parameter
    // instead of passing Class[_] instance
    println(fooBetter[String]) // output -> it's String
    println(fooBetter[B[Int]]) // output -> it's B
    println(fooBetter[A]) // output -> it's A
    println(fooBetter[List[String]]) // output -> it's list

    // This becomes even more useful when u have other parameters to
    // pass too like in bar
    println(bar[String](1)) // output -> it's String and 1
    println(bar[B[Int]](1)) // output -> it's B and 1
    println(bar[A](1)) // output -> it's A and 1
    println(bar[List[String]](1)) // output -> it's list and 1

    // certainly better than notSoGoodBar

    // Therefore as long as only erased type infomation
    // is needed to match and perform action. Then classOf
    // or better ClassTag is best option
    }

    }