[SCALA] 스칼라 : 어떤 TypeTag이고 내가 그것을 어떻게 사용합니까?
SCALA스칼라 : 어떤 TypeTag이고 내가 그것을 어떻게 사용합니까?
내가 TypeTags에 대해 아는 건 그들이 어떻게 든 매니페스트를 대체한다는 것입니다. 인터넷에 대한 정보는 부족하고, 피사체의 좋은 감각으로 날을 제공하지 않습니다.
누군가가 예와 인기있는 사용 사례를 포함 TypeTags에 유용한 자료에 대한 링크를 공유한다면 나는 행복 할 것입니다. 자세한 답변과 설명도 환영합니다.
해결법
-
==============================
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의 차이점에 대한 자세한 설명은이 질문을 참조
스칼라의 공식 문서 사이트는 반사에 대한 가이드가 포함되어 있습니다.
from https://stackoverflow.com/questions/12218641/scala-what-is-a-typetag-and-how-do-i-use-it by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 왜 예는 컴파일되지 않습니다 (공동, 콘트라 및 IN-) 분산 작업을 수행 일명 어떻게? (0) | 2019.10.29 |
---|---|
[SCALA] 자기 유형과 특성 서브 클래스의 차이점은 무엇입니까? (0) | 2019.10.28 |
[SCALA] 중괄호와 괄호 사이 스칼라의 공식 차이는 무엇, 그리고 때 사용해야인가? (0) | 2019.10.28 |
[SCALA] 무엇`을 수행합니다 _ *`(콜론 스타 밑줄) 스칼라합니까? (0) | 2019.10.28 |
[SCALA] 작업하지 직렬화 : java.io.NotSerializableException 클래스 만하지 개체에 대한 폐쇄 외부 함수를 호출 할 때 (0) | 2019.10.28 |