스칼라 : TypeTag 란 무엇이며 어떻게 사용합니까?
TypeTag에 대해 내가 아는 전부는 어떻게 든 매니페스트를 대체한다는 것입니다. 인터넷에 관한 정보는 희소하며 그 주제에 대한 올바른 이해를 제공하지 않습니다.
따라서 누군가가 예제 및 널리 사용되는 유스 케이스를 포함하여 TypeTag에 대한 유용한 자료에 대한 링크를 공유하면 기쁠 것입니다. 자세한 답변과 설명도 환영합니다.
A는 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에 도입되었습니다. 그러나 그들은 경로 의존형과 같은 유용한 유형을 많이 표현할 수 없다는 문제가 있습니다.
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
따라서 TypeTags 로 대체되어 사용이 훨씬 간단하고 새로운 Reflection API에 잘 통합되었습니다. 그것들로 우리는 경로 의존형에 관한 위의 문제를 우아하게 해결할 수 있습니다.
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
후자는 구조적 평등을 검사하는데, 이는 접두사와 같은 것을 신경 쓰지 않기 때문에 수행해야 할 일이 아닙니다 (예와 같이).
A TypeTag
는 완전히 컴파일러에서 생성됩니다. 즉, 컴파일러 TypeTag
는 a를 기대하는 메소드를 호출 할 때 작성하여 작성 합니다 TypeTag
. 태그에는 세 가지 형태가 있습니다.
- scala.reflect.ClassTag
- scala.reflect.api.TypeTags # TypeTag
- scala.reflect.api.TypeTags # WeakTypeTag
ClassTag
대체품 ClassManifest
반면 TypeTag
에 대한 다소간 대체 Manifest
.
전자는 일반 배열을 완전히 사용할 수 있습니다.
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
하나는, 방법을 볼 수 있듯이 tpe
의 TypeTag
전체에 결과를 Type
때 우리가 얻을 동일하다, 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
???
}
}
경우 일 명을 대체 WeakTypeTag
에 TypeTag
오류가 발생합니다 :
<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]
^
의 차이점에 대한보다 자세한 설명 TypeTag
과 WeakTypeTag
:이 질문에 참조 "해결되지 않은 형식 매개 변수를 갖는 타입 T에서 TypeTag를 만들 수 없습니다": 스칼라 매크로
Scala의 공식 문서 사이트에는 Reflection에 대한 안내서 도 포함되어 있습니다 .
참고 URL : https://stackoverflow.com/questions/12218641/scala-what-is-a-typetag-and-how-do-i-use-it
'Programming' 카테고리의 다른 글
ArrayList를 문자열로 변환하는 가장 좋은 방법 (0) | 2020.02.29 |
---|---|
왜 document.write가 "나쁜 습관"으로 간주됩니까? (0) | 2020.02.29 |
최대 절전 모드를 사용할 때 매개 변수 값으로 쿼리 문자열을 인쇄하는 방법 (0) | 2020.02.29 |
자식에서 병합을 미리 볼 수 있습니까? (0) | 2020.02.28 |
자바 : notify () 대 notifyAll () 다시 (0) | 2020.02.28 |