Можно ли карри наоборот в Scala? - PullRequest
5 голосов
/ 17 декабря 2009

Давайте предположим, что эта функция:

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") }

чтобы я мог отправить объекты, по которым должно быть выполнено закрытие, и выполнить для них один и тот же блок?

Ответы [ 3 ]

10 голосов
/ 17 декабря 2009

Да, фрагмент, который вы дали, работает, если вы указали тип символа-заполнителя.

Следовательно, код, который вы ищете:

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

, который компилируется и работает как положено:).

Пара заметок:

  • Вы можете упростить свою жизнь, если определите псевдоним типа для типа AnyRef, имеющего метод close, что-то вроде type Closeable = AnyRef {def close()} или соответствующий интерфейс.
  • Фрагмент кода autoClosing(_: Closeable){ ... } фактически эквивалентен следующей расширенной анонимной функции: c: Closeable => autoClosing(c){ ... }. Подстановочный знак - это просто сокращение для частично примененной функции. Вам необходимо указать тип _, так как, к сожалению, в этом случае выводчик типа не может определить тип.

Надеюсь, это поможет,

- Flaviu Cipcigan

6 голосов
/ 17 декабря 2009

В качестве альтернативы вы можете перевернуть параметры:

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

В вашем случае:

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

Edit: Я добавил несколько скобок, чтобы помочь парсеру:

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
3 голосов
/ 17 декабря 2009

Я рад видеть, что сейчас так много людей отвечают на вопросы Scala. Однако, мне все труднее придумывать что-то. Вот альтернатива Flaviu s решение .

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

Конечно, правильное решение состоит в том, чтобы определить автозавершение способом, совместимым с тем, как вы собираетесь его использовать.

...