开发者

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 a close method, something like type 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜