2009-12-17 41 views
5

假设这个函数:是否有可能在Scala中以其他方式进行咖喱?

def autoClosing(f: {def close();})(t: =>Unit) = { 
    t 
    f.close() 
} 

这个片断:

val a = autoClosing(new X)(_) 
a { 
println("before close") 
} 

是有可能咖喱第一部分?例如:

val a = autoClosing(_) { println("before close") } 

这样我就可以发送执行关闭的对象,并且对它们执行相同的块?

回答

10

是的,你给出的片段的作品,只要你给的占位符字符的类型。

因此,您正在寻找的代码是:

val a = autoClosing(_: {def close();}) { println("before close") } 

来编译和工作正常:)。

有两点要注意:

  • 你可以让你的生活更轻松,如果你定义一个类型别名的AnyRef种以上的具有close方法,像type Closeable = AnyRef {def close()},或相应的接口。
  • 代码片段autoClosing(_: Closeable){ ... }实际上等效于以下扩展的匿名函数:c: Closeable => autoClosing(c){ ... }。通配符只是部分应用函数的简写。您需要提供_的类型,因为类型传入者很遗憾无法在此情况下推断出类型。

希望它能帮助,

- Flaviu Cipcigan

+0

种类繁多。 Mersi :) – Geo 2009-12-17 11:29:21

+0

不客气。添加了几个笔记来扩大我的答案:)。不幸的是,类型inferer在这里不能推断出通配符的类型。 – 2009-12-17 11:33:28

6

或者您可以翻转的参数:

def flip[A1, A2, B](f: A1 => A2 => B): A2 => A1 => B = x1 => x2 => f(x2)(x1) 

你的情况:

val a = flip(autoClosing){ println("before close") } 

编辑: 我加了一些文胸CES帮助人类解析器:

def flip[A1, A2, B](f: (A1 => (A2 => B))): (A2 => (A1 => B)) = { 
    x1 => (x2 => f(x2)(x1)) 
} 

翻转功能(A1 => (A2 => B))转换为(A2 => (A1 => B))

scala> def x(x1 : Int)(x2 : Long) = 1.0 * x1/x2 
x: (Int)(Long)Double 

scala> val f = flip(x) 
f: (Long) => (Int) => Double = <function> 

scala> val g = f(1) 
g: (Int) => Double = <function> 

scala> val h = g(2) 
h: Double = 2.0 

scala> x(1)(2) 
res0: Double = 0.5 
+0

你能解释一下这个怪物吗? :) – Geo 2009-12-17 14:22:04

+0

我添加了一些大括号和示例代码,以便查看部分应用程序的行动。希望这可以帮助。 – 2009-12-17 14:40:27

3

我很高兴看到如此多的人现在回答斯卡拉问题。然而,它确实使我难以想出一些东西。以下是Flaviusolution的替代方案。

val a: {def close();} => Unit = autoClosing(_) { println("before close") } 

当然,妥善解决与你将如何使用它兼容的方式来定义autoClosing。

+0

我也很高兴:)。我放弃了Scala的Ruby ......它拥有我想要的所有语言。 – Geo 2009-12-17 20:04:11