我正在尝试做一些我不确定Scala的类型系统是否允许我这样做的事情。
我基本上想要从泛型定义创建一个闭包并返回该闭包,同时在同一类型内部执行一个函数。
例如:
val f = async[(str:String, i:Int, b:BigInt) => Unit]({ (String, Int, BigInt) =>
// Code here...
})
// 'f' would have a type of (String, Int, BigInt) => Unit and would wrap the passed anonymous function
定义的理论范例:
def async[T](
shell: Shell,
success: T,
failure: (Throwable) => Unit): T = {
new T {
val display = shell.getDisplay()
display.asyncExec(new Runnable() {
def run(): Unit = {
try {
success(_)
} catch {
case e:Throwable =>
failure(e)
}
}
})
}
}
这将允许我有一个简单的系统来为SWT创建异步回调,同时保持SWT不受我的业务逻辑的影响。
答案 0 :(得分:9)
您可以使用Shapeless库更一般地执行此操作。我们将wrap
定义如下:
import shapeless._, Functions._
def wrap[F, A <: HList, R](f: F)(implicit
h: FnHListerAux[F, A => R],
u: FnUnHListerAux[A => R, F]
): F = { (args: A) =>
println("Before f")
val result = f.hlisted(args)
println("After f")
result
}.unhlisted
然后可以像这样使用它:
scala> val sum: (Int, Int) => Int = _ + _
sum: (Int, Int) => Int = <function2>
scala> val wrappedSum = wrap(sum)
wrappedSum: (Int, Int) => Int = <function2>
scala> wrappedSum(100, 1)
Before f
After f
res0: Int = 101
这适用于任何arity的功能。
所以在Scala中是可能的,尽管做一些没有Shapeless的东西几乎肯定会是一个巨大的麻烦。
答案 1 :(得分:2)
这些方面的内容如何:
scala> def wrap[T1, T2, T3, R](f: (T1, T2, T3) => R) = {
| (v1: T1, v2: T2, v3: T3) =>
| println("Before f")
| val r = f(v1, v2, v3)
| println("After f")
| r
| }
wrap: [T1, T2, T3, R](f: (T1, T2, T3) => R)(T1, T2, T3) => R
scala> def foo(x: String, y: Int, z: BigInt) = (x, y, z)
foo: (x: String, y: Int, z: BigInt)(String, Int, BigInt)
scala> val wrapped = wrap(foo _)
wrapped: (String, Int, BigInt) => (String, Int, BigInt) = <function3>
scala> wrapped("foo", 42, 12345)
Before f
After f
res0: (String, Int, BigInt) = (foo,42,12345)
如果要包装的函数可以包含不同数量的参数,那么不幸的是,您必须为每个不同的arity定义一次wrap函数: - (