Resolving implicit parameter at runtime

时间:2016-03-04 17:48:04

标签: scala apache-spark implicit

I know implicits are resolved during compilation time, so I guess I'm looking for a workaround for the following. Let's say I have a method with this signature:

class MyClass {
  def run[X](x: X)(implicit runnable: Runnable[X]) = runnable(x)
}

I want to wrap it:

class MyClassWrapper[Z: ClassTag] {
  val rdd: RDD[Z] = //Spark RDD
  def runWrapper[X](fun: Z => X) = rdd.foreach( (el:Z) => new MyClass.run(fun(el)))
}

This will not compile complaining about not being able to find an implicit. I could change the signature to:

def runWrapper[X](fun: Z => X)(implicit runnable: Runnable[X])

And all would compile but I'm using Spark which does not allow not Serializable objects to be captured inside operations from the outside (in my case the run would capture the implicit parameter from runWrapper) so I do need to get/create that implicit inside the run instead of closing it in from outside. Is that possible?

2 个答案:

答案 0 :(得分:0)

您可以尝试在foreach中实现隐式:

def runWrapper[X](fun: Z => X) = rdd.foreach{ (el:Z) => 
   val runnable = implicitly[Runnable[X]]
   new MyClass.run(fun(el))(runnable)
}

答案 1 :(得分:0)

无法在运行时提出任何事情(不想尝试反射)所以我最终写了几个版本的方法,每种类型一个(因为它们不共享任何共同的父级)

class MyClassWrapper[Z: ClassTag] {
  val rdd: RDD[Z] = //Spark RDD
  def runWrapper(fun: Z => Implementation1) = rdd.foreach( (el:Z) => new MyClass.run(fun(el)))

  def runWrapper(fun: Z => Implementation2) = rdd.foreach( (el:Z) => new MyClass.run(fun(el)))
}