একটি 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
সুতরাং, এগুলি টাইপট্যাগগুলি দ্বারা প্রতিস্থাপিত হয় , যা উভয়ই ব্যবহার করতে অনেক সহজ এবং নতুন প্রতিচ্ছবি এপিআইতে ভালভাবে সংহত করা হয়। তাদের সাথে আমরা পথ-নির্ভর-প্রকারগুলি সম্পর্কে মার্জিতভাবে উপরের সমস্যাটি সমাধান করতে পারি:
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
যখন এমন পদ্ধতি প্রত্যাশিত একটি পদ্ধতি তৈরি করে এবং পূরণ করে TypeTag
। ট্যাগের তিনটি পৃথক রূপ রয়েছে:
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
দেখুন: স্কালার ম্যাক্রোস: "অমীমাংসিত টাইপ পরামিতি থাকা টাইপ টি থেকে টাইপট্যাগ তৈরি করতে পারে না"
স্কালার অফিসিয়াল ডকুমেন্টেশন সাইটে প্রতিবিম্বের জন্য একটি গাইড রয়েছে ।