【问题标题】:Resolving implicit parameter at runtime在运行时解析隐式参数
【发布时间】:2016-03-04 17:48:03
【问题描述】:

我知道隐式在编译期间已解决,所以我想我正在寻找以下解决方法。假设我有一个带有这个签名的方法:

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

我想把它包起来:

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

这不会编译抱怨无法找到隐式。我可以将签名更改为:

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

所有都可以编译,但我使用的是 Spark,它不允许从外部的操作内部捕获不可序列化的对象(在我的情况下,run 将捕获来自runWrapper 的隐式参数)所以我确实需要获取/创建隐式 inside run,而不是从外部将其关闭。那可能吗?

【问题讨论】:

  • 创建类时不能获取参数吗?即MyClassWrapper[Z](implicit runnable: Runnable[Z])?当Z 的类型已知时,需要解析implicit
  • @yw3410 它需要X 的runnable(fun 函数的结果),而不是Z,因此它在MyClassWrapper 创建时不可用。
  • 我不相信这是可能的,因为 implicit 在解决之前需要是已知类型。但是,我认为如果您知道X 的所有可能值(如果有点混乱),您将能够获得您想要的行为。你知道X 的所有可能类型吗?
  • 我可以浏览库的源代码并获得它们,但这并不是我真正想要的解决方案。

标签: scala apache-spark implicit


【解决方案1】:

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

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

【讨论】:

  • 这会生成与显式添加参数作为隐式参数相同的代码,因此不是 Mateusz 正在寻找的。 (隐式只是一种不同的方式来事实上拥有一个隐式参数列表而不直接编写它)
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2015-08-30
    • 2010-10-26
    • 1970-01-01
    • 2012-01-27
    • 2013-12-27
    • 2015-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多