Passando una funzione Scala a un metodo Java 8


18

Il seguente codice Scala funziona e può essere passato a un metodo Java in attesa di una funzione. C'è un modo più pulito per farlo? Ecco il mio primo passaggio:

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] = ???
}

Ecco il mio secondo passaggio: utilizza un wrapper generico per l'interfaccia della funzione Java-8 per semplificare la sintassi di 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)

Possiamo fare di meglio?

Come follow-up, c'è qualche possibilità che Scala un giorno userà il codice operativo invoke-dynamic come fa Java 8 per la sua applicazione di prima classe? Farà funzionare tutto magicamente o ci sarà ancora bisogno di una conversione sintattica?

Risposte:


10

Puoi rendere implicita la conversione:

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

In realtà non è necessario eseguire l'override composee andThen, ma forse il compilatore Scala non è ancora a conoscenza dei metodi di interfaccia predefiniti di Java 8. (EDIT: dovrebbe funzionare in 2.10.3.)

Inoltre, dovresti essere in grado di assegnare Scala lambdas (cioè x => ...) a Functione qualsiasi altro tipo SAM in Scala 2.11 e Java 8 lambdas a Function1. (EDIT: questo è stato effettivamente aggiunto in Scala 2.12, non 2.11.)


you should be able to assign Scala lambdas- Ciò significa che, in Scala 2.11, una funzione Scala può essere passata come argomento per un Lambda Java8?
Kevin Meredith,

Se può essere passato come argomento dipende dal tipo di lambda; se è ad esempio java.util.function.Consumer[scala.Function1[Integer, String]], può essere fatto anche prima della 2.11.
Alexey Romanov,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.