Is it possible to curry the other way around in Scala?
Let's assume this function:
def autoClo开发者_StackOverflow中文版sing(f: {def close();})(t: =>Unit) = {
t
f.close()
}
and this snippet:
val a = autoClosing(new X)(_)
a {
println("before close")
}
is it possible to curry the first part? Something like:
val a = autoClosing(_) { println("before close") }
so that I could send the objects on which close should be performed, and have the same block executed on them?
Yes, the snippet you have given works, as long as you give the type of the placeholder character.
Therefore, the code you are looking for is:
val a = autoClosing(_: {def close();}) { println("before close") }
which compiles and works as expected :).
A couple of notes:
- You can make your life easier if you define a type alias for an
AnyRef
type having aclose
method, something liketype Closeable = AnyRef {def close()}
, or an appropriate interface. - The code snippet
autoClosing(_: Closeable){ ... }
is actually equivalent to the following expanded anonymous function:c: Closeable => autoClosing(c){ ... }
. The wildcard character is just shorthand for a partially applied function. You need to give the type of the_
as the type inferer unfortunately cannot infer the type in this case.
Hope it helps,
-- Flaviu Cipcigan
Alternatively you can flip the parameters:
def flip[A1, A2, B](f: A1 => A2 => B): A2 => A1 => B = x1 => x2 => f(x2)(x1)
In your case:
val a = flip(autoClosing){ println("before close") }
Edit: I've added some braces to help the human parser:
def flip[A1, A2, B](f: (A1 => (A2 => B))): (A2 => (A1 => B)) = {
x1 => (x2 => f(x2)(x1))
}
Flip converts a function (A1 => (A2 => B))
to (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
I'm happy to see so many people answering Scala questions nowadays. It does make it harder for me to come up with something, however. Here's an alternative to Flaviu's solution.
val a: {def close();} => Unit = autoClosing(_) { println("before close") }
Of course, the proper solution is to define autoClosing in a way compatible with how you are going to use it.
精彩评论