在Scala中创建从泛型闭包
我正在尝试做一些我不确定Scala的类型系统是否允许我这样做的事情。在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出来的我商业逻辑。
您可以用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中是可能的,尽管做一些没有无形体的东西几乎肯定会让人头疼。
这看起来非常有趣!它不会导致任何(显着的)运行时开销,例如,通过使用反射? – 2012-07-16 06:54:43
不,没有反射。运行时间开销,但不应该过多 – 2012-07-16 07:00:12
谢谢,这正是我想要的,这可能会成为将匿名类转换为匿名函数的非常有用的模式。 – Hakkar 2012-07-16 21:15:37
如何沿着这些路线的东西:
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)
如果你想换行可以有争论,那么你将很不幸,有一次定义您的包裹功能为每个不同的元数不同数量的功能: - (
感谢您的回答。不同数量的参数部分是不幸的:(尽管如此,你可以强制这个监听器采用一个单独的元组,并通过这种类型的方式来绕过这个限制,能够转发泛型类型是非常棒的。我不确定Scala是否有这样的功能:/。 – Hakkar 2012-07-16 02:19:30
可能的重复[斯卡拉泛型 - 为什么我不能在泛型类中创建参数化对象?](http://stackoverflow.com/questions/5336648/scala-generics-why-i-cant-create-parametrised- object-inside-generic-class) – 2012-07-15 23:49:14
我不认为它是100%重复的,因为即使我用apply方法创建了一个类型为T的类,我仍然需要接受由T提供的适当参数。 ,类型擦除可能会使这个特定的问题无法解决。 – Hakkar 2012-07-16 02:24:16