我正在尝试编写一个接受多个泛型类型的方法,并将一个工作单元作为参数来执行。
这个想法是工作单元是一个共同的功能,它本身就是通用的。例如,让我们说它类似于以下内容:
def loadModelRdd[T: TypeTag](sc: SparkContext): RDD[T] = {
...
}
loadModelRdd()将在进行一些内部处理(如加载模型信息等)后构造给定类型的RDD。
我一直在攻击的原型方法看起来像以下(非工作):
def forkAll[A : Manifest, B : Manifest](work: => RDD[_]): (RDD[A], RDD[B]) = {
def aFuture = Future { work } // How can I notify that this work call returns type A?
def bFuture = Future { work } // How can I notify that this work call returns type B?
val res = for {
a <- aFuture
b <- bFuture
} yield (a.asInstanceOf[A], b.asInstanceOf[B])
Await.result(res, 10.seconds)
}
这是我正在处理的代码的缩短版本,因为我实际上正在考虑接受多达10种不同的类型。
正如您所看到的,forkAll方法的总体目标是将工作单元包装在Future中,fork-join执行每种类型的工作单元,然后将结果作为元组结果返回。消费者声明的示例如下:
val (a, b) = forkAll[ClassA, ClassB](loadModelRdd)
即我想在此时进行fork-join并等待结果,但我希望执行并行执行,然后收集回Driver(Spark Driver具体)。
问题是我不确定在构造Future {}块时如何强制forkAll中的工作单元返回的类型。没有forkAll,实现如下所示:
val resA = loadModelRdd[ClassA](sc)
val resB = loadModelRdd[ClassB](sc)
...
我正在考虑这样做有两个原因:
在Scala的类型系统中,这是可能的吗?或者我应该从不同的角度看待这个问题?我已经尝试了几个实现(包括一个描述here),但我还没有找到一个适合我当前对问题的看法
如果需要任何其他信息,请与我们联系。
谢谢!
答案 0 :(得分:0)
简短回答: Scala does not allow functions with type parameters,所以你想要的并不完全可能。
您正在尝试使用类型参数传递方法。虽然允许方法具有类型参数,但函数不允许。当您尝试传递方法时,它的作用类似于匿名函数,因此您必须指定类型。
但是,由于方法确实允许使用类型参数,因此您可以通过创建将执行fork / join的抽象类来利用此功能
abstract class ForkJoin {
protected def work[T]: RDD[T]
def apply[A, B]: (RDD[A], RDD[B]) = {
// Write implementation of fork/join here
(work[A], work[B])
}
}
然后覆盖类型泛型work
方法,以便它可以执行您想要的操作,例如调用其他预定义方法。
val forkJoin = new ForkJoin {
override protected def work[T]: RDD[T] =
loadModelRdd[T](sc)
}
val (intRdd, stringRdd) = forkJoin[Int, String]
查看this,了解编译和运行没有问题的原型实现。