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.