Передача функції Scala методу Java 8


18

Наступний код Scala працює і може бути переданий методу Java, який очікує функції. Чи є чистіший спосіб зробити це? Ось мій перший пропуск:

val plusOne = new java.util.function.Function[Int,Int] {
  override def apply(t:Int):Int = t + 1

  override def andThen[V](after:function.Function[_ >: Int, _ <: V]):
    function.Function[Int, V] = ???

  override def compose[V](before:function.Function[_ >: V, _ <: Int]):
    function.Function[V, Int] = ???
}

Ось мій другий пропуск - він використовує загальну обгортку для інтерфейсу функції Java-8, щоб зробити синтаксис Scala простішим:

// Note: Function1 is Scala's functional interface,
// Function (without the 1) is Java 8's.
case class JavaFunction1[U,V](f:Function1[U,V]) extends Function[U,V] {
  override def apply(t: U): V = f(t)
  override def compose[T](before:Function[_ >: T, _ <: U]):
    Function[T, V] = ???
  override def andThen[W](after:Function[_ >: V, _ <: W]):
    Function[U, W] = ???
}

val plusOne = JavaFunction1((x:Int) => x + 1)
val minusOne = JavaFunction1((x:Int) => x - 1)

Чи можемо ми зробити краще?

Як надалі, чи є шанс, що колись Скала скористається динамічним викликом оп-коду, як це робить Java 8 для свого першокласного додатка? Чи змусить це все магічно спрацювати, чи все-таки потрібно буде синтаксичне перетворення?

Відповіді:


10

Перетворення можна зробити неявним:

implicit def toJavaFunction[U, V](f:Function1[U,V]): Function[U, V] = new Function[U, V] {
  override def apply(t: U): V = f(t)

  override def compose[T](before:Function[_ >: T, _ <: U]):
    Function[T, V] = toJavaFunction(f.compose(x => before.apply(x)))

  override def andThen[W](after:Function[_ >: V, _ <: W]):
    Function[U, W] = toJavaFunction(f.andThen(x => after.apply(x)))
}

implicit def fromJavaFunction[U, V](f:Function[U,V]): Function1[U, V] = f.apply

Ви не повинні на насправді потрібно перевизначити composeі andThen, може бути , але Scala компілятор не знає про методи інтерфейсу 8 по замовчуванням Java ще. (EDIT: це має працювати в 2.10.3.)

Крім того, ви повинні мати можливість призначити лямбда Scala (тобто x => ...) для Functionбудь-яких інших типів SAM у Scala 2.11 та лямбдах Java 8 Function1. (EDIT: це фактично додано в Scala 2.12, а не 2.11.)


you should be able to assign Scala lambdas- Це означає, що в Scala 2.11 функцію Scala можна передавати як аргумент для Java8 Lambda?
Кевін Мередіт

Чи можна це пропустити як аргумент, залежить від типу лямбда; якщо це, наприклад, java.util.function.Consumer[scala.Function1[Integer, String]]тоді це можна зробити і до 2.11.
Олексій Романов
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.