SORU
31 AĞUSTOS 2012, Cuma


Bir TypeTag Nedir ve nasıl kullanırım?Scala:

TypeTags hakkında bildiğim tek şey bir şekilde Tezahür yerini aldı. İnternette bilgiler azdır ve konuyla iyi bir duygusu ile beni sağlamaz.

Eğer birileri örnekler de dahil olmak üzere TypeTags bazı yararlı malzemeleri bir bağlantı paylaştı olursa mutlu olurum ve popüler durumlarda kullanın. Ayrıntılı cevaplar ve açıklamalar da memnuniyetle karşılanıyor.

CEVAP
1 EYLÜL 2012, CUMARTESİ


TypeTag Bir tür çalışma zamanında silinir Scalas sorun (tür silme) çözer. Eğer biz yapmak istiyorum

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"
}

uyarı alacağız:

<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"
                 ^

Bu sorunu çözmek için Manifests Scala tanıtıldı. Ama sorun yol-bağımlı-türleri gibi yararlı türleri, bir sürü temsil edememek var:

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

Böylece, çok kullanmak daha basit ve yeni Yansıma API içine entegre her ikisi de olan TypeTags ile değiştirilir. Onlarla yukarıda yol-bağımlı tipte zarif hakkında: bu sorunu çözebiliriz

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

Ayrıca kolay tür parametreleri kontrol etmek için kullanmak

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

Bu noktada, anlamak için son derece önemli eşitlik denetler =:= (Bir tür eşitlik) ve <:< (alt tür ilişkisi) kullanın. Sen istediğini kesinlikle bilmedikçe == !=, kullanın asla:

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

Genellikle önekler gibi şeyler (örnekte olduğu gibi) umurumda değil, çünkü ne yapılması gerektiğini değil, hangi yapısal eşitlik için son kontroller.

Tek bir yöntem TypeTag böyle bir bekliyor çağırdığında TypeTag tamamen derleyici oluşturur doldurur anlamına gelir derleyici tarafından oluşturulan bir TypeTag. Etiketleri üç farklı formları vardır:

ClassTag yerine TypeTag oysa ClassManifest Manifest için daha fazla ya da daha az yerine geçer.

Eski tamamen jenerik dizi ile çalışmak için izin verir:

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 sadece bilgi çalışma zamanı tür silinir): türleri oluşturmak için gerekli sağlar

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]

Bir, bu nedenle eğer bir "TypeTag kullanılmalıdır türleri:." tam istediği tip silme hakkında umurlarında değil, yukarıda gördüğünüz gibi

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

Görüldüğü gibi, yöntem tam TypeTag sonuçlar tpe aynı Type, typeOf denir. Elbette mümkün, ClassTag TypeTag kullanmak için:

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]])

Kalan soru şimdi WeakTypeTag duygusu nedir ? Kısacası, 43* *temsil WeakTypeTag sadece herhangi bir tür verir; somut bir tip (bu sadece tam olarak oluşturulmuş türleri sağlar anlamına gelir). Çoğu zaman bir değildir umurunda olan ne (yani TypeTag kullanılmalıdır), ama örneğin, makro, kullanılan zaman ise yarar ile genel türler bunlar gerekli:

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
    ???
  }
}

Eğer bir TypeTag 47 *değiştirir eğer bir hata atılır:

<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 arasındaki farklar hakkında daha ayrıntılı bir açıklama için bu soruya bakın: Scala Macros: “cannot create TypeTag from a type T having unresolved type parameters”

Scala resmi belge, site de guide for Reflection içerir.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Glyn Dewis

    Glyn Dewis

    25 AĞUSTOS 2007
  • Kingsimba357

    Kingsimba357

    7 NİSAN 2008
  • Rachel Talbott

    Rachel Talbo

    26 Ocak 2011