Truyền hàm Scala cho phương thức Java 8


18

Mã Scala sau đây hoạt động và có thể được truyền cho một phương thức Java mong đợi một hàm. Có cách nào sạch hơn để làm điều này? Đây là đường chuyền đầu tiên của tôi:

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

Đây là lần thứ hai của tôi - nó sử dụng trình bao bọc chung cho giao diện Hàm Java-8 để làm cho cú pháp Scala đơn giản hơn:

// 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)

Chúng ta có thể làm tốt hơn không?

Theo dõi, có bất kỳ cơ hội nào mà Scala một ngày nào đó sẽ sử dụng mã op-invoke-Dynamic như Java 8 làm cho ứng dụng hàm hạng nhất của nó không? Điều đó sẽ làm cho mọi thứ hoạt động kỳ diệu, hay vẫn sẽ cần phải có một chuyển đổi cú pháp?

Câu trả lời:


10

Bạn có thể thực hiện chuyển đổi ngầm định:

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

Bạn thực sự không cần phải ghi đè composeandThen, nhưng có lẽ trình biên dịch Scala chưa biết về các phương thức giao diện mặc định của Java 8. (EDIT: nó sẽ hoạt động trong 2.10.3.)

Ngoài ra, bạn sẽ có thể gán Scala lambdas (tức là x => ...) cho Functionvà bất kỳ loại SAM nào khác trong Scala 2.11 và Java 8 lambdas cho Function1. (EDIT: điều này thực sự đã được thêm vào trong Scala 2.12, không phải 2.11.)


you should be able to assign Scala lambdas- Điều này có nghĩa là, trong Scala 2.11, một hàm Scala có thể được truyền làm đối số cho Lambda Java8 không?
Kevin Meredith

Việc nó có thể được thông qua như một đối số hay không tùy thuộc vào loại lambda; nếu đó là ví dụ java.util.function.Consumer[scala.Function1[Integer, String]]thì nó cũng có thể được thực hiện trước 2.11.
Alexey Romanov
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.