2012-07-18 61 views
2

我在想这可能是无形的库。用函数替换异步匿名类

我正在使用无形来将匿名类转换为闭包。这需要使用来自FnHListerAux特征的hlisted

我想要做的就是摆脱传入的虚拟函数,并返回与此函数具有相同类型签名的闭包,如F。如果没有异步执行的匿名类,这很容易。有没有办法解决这个问题?

def async[F, A <: HList, R](
    shell: Shell, 
    success: F, 
    failure: FunctionTypes.Failure, 
    dummy: F)(implicit h: FnHListerAux[F, A => R], 
      u: FnUnHListerAux[A => R, F]): F = 
{ (args: A) => 

    require(shell != null, "Shell cannot be null") 
    require(shell.getDisplay() != null, "The shell must have a display") 

    val display = shell.getDisplay() 
    display.asyncExec(new Runnable() { 
    def run(): Unit = { 
     try { 
     success.hlisted(args) 
     } catch { 
     case e: Throwable => 
      failure(e) 
     } 
    } 
    }) 

    dummy.hlisted(args) 
}.unhlisted 
+0

如果你需要像这样的无意义的东西,你的算法必定会有一些严重的问题。试着解释你需要什么。 – 2012-07-18 00:45:26

+0

当然,这是一个好主意。我对Scala很陌生。我仍然很好奇,看看你是否真的可以取代一个函数的主体。但是,对于我的实际问题,解决方案很可能存在于不成形的图书馆中,这超出了我的知识水平,我仍然试图理解它的本质。 – Hakkar 2012-07-18 00:58:03

回答

3

我首先简化一下。假设我有一个功能f。事先我不知道它是什么样的,我不在乎它返回的是什么。我想用一些功能来包装它,并获得具有相同参数类型的函数。我也不在乎这个结果函数返回什么,所以我不妨将它返回Unit

你可以写类似下面的功能一堆(当然,22):

def wrap[A](f: A => Unit): A => Unit = ??? 
def wrap[A, B](f: (A, B) => Unit): (A, B) => Unit = ??? 
def wrap[A, B, C](f: (A, B, C) => Unit): (A, B, C) => Unit = ??? 

但你不想。

无形的,绝对可以帮你解决这个问题更一般:

def wrap[F, A <: HList](f: F)(
    implicit h: FnHListerAux[F, A => Unit], u: FnUnHListerAux[A => Unit, F] 
): F = { (args: A) => 
    println("Before!"); f.hlisted(args); println("After!") 
}.unhlisted 

这给了我们:

scala> def f(i: Int, s: String) { println(s * i) } 
f: (i: Int, s: String)Unit 

scala> val wf = wrap(f _) 
wf: (Int, String) => Unit = <function2> 

scala> wf(3, "ab") 
Before! 
ababab 
After! 

注意f可以返回其他的东西比Unit,这将仍然工作,因为一切在斯卡拉是一个UnitFunctionN特征协调在他们的返回类型。

运用这种方法来验证码,我们得到如下:

def async[F, A <: HList](
    shell: Shell, success: F, failure: FunctionTypes.Failure 
)(
    implicit h: FnHListerAux[F, A => Unit], u: FnUnHListerAux[A => Unit, F] 
): F = { (args: A) => 
    require(shell != null, "Shell cannot be null") 
    require(shell.getDisplay() != null, "The shell must have a display") 

    val display = shell.getDisplay() 
    display.asyncExec(new Runnable() { 
    def run(): Unit = { 
     try { 
     success.hlisted(args) 
     } catch { 
     case e: Throwable => 
      failure(e) 
     } 
    } 
    }) 
}.unhlisted 

无需dummy

+0

再次感谢特拉维斯:) – Hakkar 2012-07-18 21:39:04