我在 Scala 代碼(Scala 2.13)中有一個這樣的函式,用于 Spark
def getDataset[T <: Product: TypeTag](name:String): Dataset[T] = {
import spark.implicits._
val ds = spark.read.parquet(BASE_PATH "/" name).as[T]
ds.createOrReplaceTempView(name)
ds
}
現在我想轉一個Seqcase類,對于每個類,呼叫這個函式:
case class CLASS1(...)
case class CLASS2(...)
case class CLASS3(...)
Seq(CLASS1, CLASS2, CLASS3, ....).foreach {
c => getDataset[c??](name=c???)
}
我很難弄清楚確切的語法;為的情況下的類,由變數表示的名稱的符號c內foreach,似乎代表所述的型別apply的方法(() => Product)。我真正想要的是該型別的案件類作為型別引數的使用,以及名稱的情況下類。
感覺我應該能夠做到這一點 - 我在這里錯過了什么?
uj5u.com熱心網友回復:
您可以為案例類定義自己的伴隨物件,并在每個物件中包含一個呼叫getDataset. 例如,這應該有效(由我的心理編譯器傳遞):
abstract class DatasetProvider[T <: Product : TypeTag] {
val name: String
def dataset: Dataset[T] =
getDataset[T](name)
}
case class Class1(...)
object Class1 extends DatasetProvider[Class1] {
override val name: String = "class1"
}
// and so forth for Class2, Class3
Seq(Class1, Class2, Class3).foreach { c =>
val ds = c.dataset
???
}
請注意,如果定義您自己的伴生物件,如果您想將其用作一個函式,則必須將其顯式標記為一個函式:這可能是可取的,也可能是不可取的。
uj5u.com熱心網友回復:
問題是您想要T在型別級別和name(在運行時已知)在值級別替換(在編譯時已知)。
通常T和name不同時存在。
一種選擇是將Seq(Class1, Class2, Class3)值級別替換Class1 :: Class2 :: Class3 :: HNil為型別級別并使用Shapeless
import shapeless.{::, HNil, Poly0, Poly1, Typeable}
import shapeless.ops.hlist.FillWith
import scala.reflect.runtime.universe.{TypeTag, typeOf}
object datasetPoly extends Poly1 {
implicit def cse[T <: Product : TypeTag /*: Typeable*/]: Case.Aux[T, Dataset[T]] =
at(_ => getDataset[T](/*Typeable[T].describe*/typeOf[T].toString))
}
object nullPoly extends Poly0 {
implicit def cse[T >: Null]: Case0[T] = at(null)
}
FillWith[nullPoly.type, Class1 :: Class2 :: Class3 :: HNil].apply().map(datasetPoly)
或者,您可以使用宏或運行時反射。在Seq(Class1, Class2, Class3) Class1、Class2、 中Class3是 case 類的伴隨物件。例如使用反射工具箱
import scala.reflect.runtime.universe.Quasiquote
import scala.reflect.runtime.{currentMirror => cm}
import scala.tools.reflect.ToolBox
val tb = cm.mkToolBox()
Seq(Class1, Class2, Class3).foreach(c => {
val classSymbol = cm.reflect(c).symbol.companion
tb.eval(q"App.getDataset[$classSymbol](${classSymbol.name.toString})")
})
你應該添加到 build.sbt
libraryDependencies = scalaOrganization.value % "scala-reflect" % scalaVersion.value
libraryDependencies = scalaOrganization.value % "scala-compiler" % scalaVersion.value
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/322622.html
