2009-12-17 37 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