복붙노트

[SCALA] 스칼라 : 어떤 TypeTag이고 내가 그것을 어떻게 사용합니까?

SCALA

스칼라 : 어떤 TypeTag이고 내가 그것을 어떻게 사용합니까?

내가 TypeTags에 대해 아는 건 그들이 어떻게 든 매니페스트를 대체한다는 것입니다. 인터넷에 대한 정보는 부족하고, 피사체의 좋은 감각으로 날을 제공하지 않습니다.

누군가가 예와 인기있는 사용 사례를 포함 TypeTags에 유용한 자료에 대한 링크를 공유한다면 나는 행복 할 것입니다. 자세한 답변과 설명도 환영합니다.

해결법

  1. ==============================

    1.TypeTag 스칼라의 유형이 런타임 (유형 삭제)에서 삭제되는 문제를 해결합니다. 우리가 할 싶다면

    TypeTag 스칼라의 유형이 런타임 (유형 삭제)에서 삭제되는 문제를 해결합니다. 우리가 할 싶다면

    class Foo
    class Bar extends Foo
    
    def meth[A](xs: List[A]) = xs match {
      case _: List[String] => "list of strings"
      case _: List[Foo] => "list of foos"
    }
    

    우리는 경고를 얻을 것이다 :

    <console>:23: warning: non-variable type argument String in type pattern List[String]↩
    is unchecked since it is eliminated by erasure
             case _: List[String] => "list of strings"
                     ^
    <console>:24: warning: non-variable type argument Foo in type pattern List[Foo]↩
    is unchecked since it is eliminated by erasure
             case _: List[Foo] => "list of foos"
                     ^
    

    매니페스트 스칼라에 도입 된이 문제를 해결합니다. 그러나 그들은 문제가 경로 의존적-유형과 같은 유용한 유형을 많이 표현할 수없는이 :

    scala> class Foo{class Bar}
    defined class Foo
    
    scala> def m(f: Foo)(b: f.Bar)(implicit ev: Manifest[f.Bar]) = ev
    warning: there were 2 deprecation warnings; re-run with -deprecation for details
    m: (f: Foo)(b: f.Bar)(implicit ev: Manifest[f.Bar])Manifest[f.Bar]
    
    scala> val f1 = new Foo;val b1 = new f1.Bar
    f1: Foo = Foo@681e731c
    b1: f1.Bar = Foo$Bar@271768ab
    
    scala> val f2 = new Foo;val b2 = new f2.Bar
    f2: Foo = Foo@3e50039c
    b2: f2.Bar = Foo$Bar@771d16b9
    
    scala> val ev1 = m(f1)(b1)
    warning: there were 2 deprecation warnings; re-run with -deprecation for details
    ev1: Manifest[f1.Bar] = Foo@681e731c.type#Foo$Bar
    
    scala> val ev2 = m(f2)(b2)
    warning: there were 2 deprecation warnings; re-run with -deprecation for details
    ev2: Manifest[f2.Bar] = Foo@3e50039c.type#Foo$Bar
    
    scala> ev1 == ev2 // they should be different, thus the result is wrong
    res28: Boolean = true
    

    따라서, 그들은 둘 다 사용하는 것이 훨씬 간단하고도 새로운 리플렉션 API에 통합되어 TypeTags에 의해 대체된다. 그들과 우리는 우아에 대한 경로 의존-유형 위의 문제를 해결할 수 있습니다 :

    scala> def m(f: Foo)(b: f.Bar)(implicit ev: TypeTag[f.Bar]) = ev
    m: (f: Foo)(b: f.Bar)(implicit ev: reflect.runtime.universe.TypeTag[f.Bar])↩
    reflect.runtime.universe.TypeTag[f.Bar]
    
    scala> val ev1 = m(f1)(b1)
    ev1: reflect.runtime.universe.TypeTag[f1.Bar] = TypeTag[f1.Bar]
    
    scala> val ev2 = m(f2)(b2)
    ev2: reflect.runtime.universe.TypeTag[f2.Bar] = TypeTag[f2.Bar]
    
    scala> ev1 == ev2 // the result is correct, the type tags are different
    res30: Boolean = false
    
    scala> ev1.tpe =:= ev2.tpe // this result is correct, too
    res31: Boolean = false
    

    또한 유형 매개 변수를 확인하기 위해 쉽게 사용할 수 있습니다 :

    import scala.reflect.runtime.universe._
    
    def meth[A : TypeTag](xs: List[A]) = typeOf[A] match {
      case t if t =:= typeOf[String] => "list of strings"
      case t if t <:< typeOf[Foo] => "list of foos"
    }
    
    scala> meth(List("string"))
    res67: String = list of strings
    
    scala> meth(List(new Bar))
    res68: String = list of foos
    

    평등 검사를위한 <(하위 관계) = (유형 평등)과 <: 지금부터, =를 사용하여 이해하는 것이 매우 중요합니다. ! 당신이 절대적으로 당신이 무엇을 알고하지 않는 == 또는 = 사용하지 마십시오 :

    scala> typeOf[List[java.lang.String]] =:= typeOf[List[Predef.String]]
    res71: Boolean = true
    
    scala> typeOf[List[java.lang.String]] == typeOf[List[Predef.String]]
    res72: Boolean = false
    

    이 것들에 대해 신경 쓰지 않기 때문에 자주 (예에서와 같이) 등의 접두사로 무엇을 수행해야되지 구조 평등에 대한 후자를 확인합니다.

    TypeTag 컴파일러가 생성 한 그러한 TypeTag 6.12 메소드를 호출 할 때 TypeTag 채우는 것을 의미 완전히 컴파일러가 생성된다. 태그의 세 가지 형태가 존재한다 :

    TypeTag 매니페스트 대한 다소간 대체 반면 ClassTag는 ClassManifest 대입.

    전자는 완전히 일반적인 배열 작업을 수행 할 수 있습니다 :

    scala> import scala.reflect._
    import scala.reflect._
    
    scala> def createArr[A](seq: A*) = Array[A](seq: _*)
    <console>:22: error: No ClassTag available for A
           def createArr[A](seq: A*) = Array[A](seq: _*)
                                               ^
    
    scala> def createArr[A : ClassTag](seq: A*) = Array[A](seq: _*)
    createArr: [A](seq: A*)(implicit evidence$1: scala.reflect.ClassTag[A])Array[A]
    
    scala> createArr(1,2,3)
    res78: Array[Int] = Array(1, 2, 3)
    
    scala> createArr("a","b","c")
    res79: Array[String] = Array(a, b, c)
    

    ClassTag 런타임에 유형 (유형이 삭제되는) 작성에 필요한 정보만을 제공합니다 :

    scala> classTag[Int]
    res99: scala.reflect.ClassTag[Int] = ClassTag[int]
    
    scala> classTag[Int].runtimeClass
    res100: Class[_] = int
    
    scala> classTag[Int].newArray(3)
    res101: Array[Int] = Array(0, 0, 0)
    
    scala> classTag[List[Int]]
    res104: scala.reflect.ClassTag[List[Int]] =↩
            ClassTag[class scala.collection.immutable.List]
    

    하나는 위에서 볼 수 있듯이, 그들은 하나가 사용되어야한다 TypeTag "전체"유형을 원하는 때문에 경우, 형의 삭제에 대해 걱정하지 않는다 :

    scala> typeTag[List[Int]]
    res105: reflect.runtime.universe.TypeTag[List[Int]] = TypeTag[scala.List[Int]]
    
    scala> typeTag[List[Int]].tpe
    res107: reflect.runtime.universe.Type = scala.List[Int]
    
    scala> typeOf[List[Int]]
    res108: reflect.runtime.universe.Type = scala.List[Int]
    
    scala> res107 =:= res108
    res109: Boolean = true
    

    사람이 볼 수 있듯이, TypeTag의 방법의 유형 대해서 typeof를 호출 할 때 우리가 얻을 동일 전체 유형, 발생합니다. 물론, ClassTag 및 TypeTag 모두를 사용할 수있다 :

    scala> def m[A : ClassTag : TypeTag] = (classTag[A], typeTag[A])
    m: [A](implicit evidence$1: scala.reflect.ClassTag[A],↩
           implicit evidence$2: reflect.runtime.universe.TypeTag[A])↩
          (scala.reflect.ClassTag[A], reflect.runtime.universe.TypeTag[A])
    
    scala> m[List[Int]]
    res36: (scala.reflect.ClassTag[List[Int]],↩
            reflect.runtime.universe.TypeTag[List[Int]]) =↩
           (scala.collection.immutable.List,TypeTag[scala.List[Int]])
    

    나머지 문제는 지금 WeakTypeTag의 의미는 무엇입니까? 즉, TypeTag는 WeakTypeTag 그냥 모든 유형을 허용하는 반면 (이것은 단지 완전히 인스턴스화을 가능하게 해주는 의미) 구체적인 유형을 나타냅니다. 하나는 상관하지 않는다 대부분의 시간을 (어떤이 TypeTag 사용해야 의미)하지만, 예를 들어, 매크로를 사용하는 경우가 필요한 일반적인 유형의 작업을해야하는 무엇이다 :

    object Macro {
      import language.experimental.macros
      import scala.reflect.macros.Context
    
      def anymacro[A](expr: A): String = macro __anymacro[A]
    
      def __anymacro[A : c.WeakTypeTag](c: Context)(expr: c.Expr[A]): c.Expr[A] = {
        // to get a Type for A the c.WeakTypeTag context bound must be added
        val aType = implicitly[c.WeakTypeTag[A]].tpe
        ???
      }
    }
    

    하나 TypeTag으로 WeakTypeTag를 교체하는 경우 오류가 발생합니다 :

    <console>:17: error: macro implementation has wrong shape:
     required: (c: scala.reflect.macros.Context)(expr: c.Expr[A]): c.Expr[String]
     found   : (c: scala.reflect.macros.Context)(expr: c.Expr[A])(implicit evidence$1: c.TypeTag[A]): c.Expr[A]
    macro implementations cannot have implicit parameters other than WeakTypeTag evidences
                 def anymacro[A](expr: A): String = macro __anymacro[A]
                                                          ^
    

    스칼라 매크로 : "해결되지 않은 형식 매개 변수를 갖는 타입 T에서 TypeTag를 만들 수 없습니다"TypeTag과 WeakTypeTag의 차이점에 대한 자세한 설명은이 질문을 참조

    스칼라의 공식 문서 사이트는 반사에 대한 가이드가 포함되어 있습니다.

  2. from https://stackoverflow.com/questions/12218641/scala-what-is-a-typetag-and-how-do-i-use-it by cc-by-sa and MIT license