Давайте примем эту функцию:
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") }
так, чтобы я мог отправить объекты, на которых близко должен быть выполнен, и тот же блок выполнился на них?
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:
AnyRef
type having a close
method, something like type Closeable = AnyRef {def close()}
, or an appropriate interface.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
Я рад видеть, что сегодня так много людей отвечают на вопросы Scala. Однако мне труднее что-то придумать. Вот альтернатива решению Flaviu .
val a: {def close();} => Unit = autoClosing(_) { println("before close") }
Конечно, правильным решением является определение автоматического закрытия способом, совместимым с тем, как вы собираетесь его использовать.
В качестве альтернативы вы можете перевернуть параметры:
def flip[A1, A2, B](f: A1 => A2 => B): A2 => A1 => B = x1 => x2 => f(x2)(x1)
В вашем случае:
val a = flip(autoClosing){ println("before close") }
Изменить: Я добавил фигурные скобки, чтобы помочь синтаксическому анализатору:
def flip[A1, A2, B](f: (A1 => (A2 => B))): (A2 => (A1 => B)) = {
x1 => (x2 => f(x2)(x1))
}
Flip преобразует функцию (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