Scala 与 Java SAM 互操作,没有 2.12 M2 标志
Scala interop with Java SAM without 2.12 M2 flag
是否有针对使用 Java @FunctionalInterface / SAM / lambda 表达式的 Java-8 API 编写 Scala 代码的公认技术?
虽然 Java lambda 表达式互操作在 M2 http://www.scala-lang.org/news/2.12.0-M2 的标志下可用,但我更希望类型 class / AnyVal 解决方案可以与 scala.FunctionX 特征。
不幸的是,scala.FunctionX 扩展了 AnyRef 而不是 Any,因此不能 use/mix 这些特性进入隐式 AnyVal class 实现。
补充:即使 scala.FunctionX 是全局特征(从 Any 扩展),我也不完全确定我会如何实现我的目标。我的用例是这样的:
在我的一个项目中,我选择提供 Java-8 API 和 Java 流接口和 class 等功能接口,以便迎合尽可能广泛的基于 JVM 的客户端语言的受众,例如闭包、Scala、Kotlin。对于使用我的 Java-8 API 的每种客户端语言,如果在访问 Java-8 API 的情况下,我将编写适当的绑定(如有必要)以使用特定于语言的习语] 用那种语言感觉笨拙。
顺便说一句。我也会对在 Kotlin-Java 互操作上下文中对这个问题发表的任何评论感兴趣。
这个 Scala 程序演示了我的问题的一面,即如何让 Scala 函数伪装成 Java 8 个 Lambdas。
从语法和惯用的角度来看,这似乎可以通过创建一些隐式 Scala 函数将 Scala 函数转换为它们的 Java 8 FunctionalInterface 对应类型。
当然,需要注意的是,此方法没有利用 Java 8 通过 invokedynamic 优化 lambda 创建的能力。
因此,这种方法会导致为 Scala 函数实例创建 JVM 对象,与 Java 8 个本机 lambda 相比,这可能会影响内存使用和性能。
对于硬币的另一面,即如何让 Java 8 个 Lambda 伪装成 Scala 函数,我想必须编写一些 Java 代码才能与 Scala 互操作(如果一个人的目标是拥有一个可从 Java 调用的 Scala API)。
贾斯汀·约翰逊,
关于我的项目发条的微博,
XPath/XQuery 在 JVM 上的新实现,
作为推特上的@MartianOdyssey
https://twitter.com/MartianOdyssey
/**
* Scala Functions masquerading as Java 8 Lambdas.
*
* (C) Justin Johansson 2015.
*
* Microblogging about my Project Clockwork, a
* new implementation of XPath/XQuery on the JVM,
* as @MartianOdyssey on Twitter (https://twitter.com/MartianOdyssey).
*
* Permission to use this code is granted under Apache License,
* Version 2.0 and providing attribution is afforded to author,
* Justin Johansson.
*/
package lab
import scala.language.implicitConversions
import java.util.{ Arrays => JArrays, List => JList }
import java.util.function.{ Consumer => JConsumer, Function => JFunction, Predicate => JPredicate }
import java.util.stream.{ Stream => JStream }
object JLambda extends App {
println("JLambda: Scala to Java 8 lambda test")
implicit def func1ToJConsumer[T](func: T => Unit): JConsumer[T] = {
new JConsumer[T] {
def accept(arg: T): Unit = func(arg)
}
}
implicit def func1ToJFunction[T, R](func: T => R): JFunction[T, R] = {
new JFunction[T, R] {
def apply(arg: T): R = func(arg)
}
}
implicit def func1ToJPredicate[T](func: T => Boolean): JPredicate[T] = {
new JPredicate[T] {
def test(arg: T): Boolean = func(arg)
}
}
val myList = JArrays.asList("cake", "banana", "apple", "coffee")
println(s"myList = $myList")
val myListFiltered: JStream[String] = myList.stream
.filter { x: String => x.startsWith("c") }
val myListFilteredAndMapped: JStream[String] = myListFiltered
.map { x: String => x.toUpperCase }
myListFilteredAndMapped.forEach { x: String => println(s"x=$x") }
}
/*
Outputs:
JLambda: Scala to Java 8 lambda test
myList = [cake, banana, apple, coffee]
x=CAKE
x=COFFEE
*/
btw. I would be interested in any comments with this question taken in a Kotlin-Java interop context also.
Kotlin 的 FunctionX
接口是 SAM 的,所以不需要做任何额外的事情来让 Java 8 理解它们
是否有针对使用 Java @FunctionalInterface / SAM / lambda 表达式的 Java-8 API 编写 Scala 代码的公认技术?
虽然 Java lambda 表达式互操作在 M2 http://www.scala-lang.org/news/2.12.0-M2 的标志下可用,但我更希望类型 class / AnyVal 解决方案可以与 scala.FunctionX 特征。
不幸的是,scala.FunctionX 扩展了 AnyRef 而不是 Any,因此不能 use/mix 这些特性进入隐式 AnyVal class 实现。
补充:即使 scala.FunctionX 是全局特征(从 Any 扩展),我也不完全确定我会如何实现我的目标。我的用例是这样的:
在我的一个项目中,我选择提供 Java-8 API 和 Java 流接口和 class 等功能接口,以便迎合尽可能广泛的基于 JVM 的客户端语言的受众,例如闭包、Scala、Kotlin。对于使用我的 Java-8 API 的每种客户端语言,如果在访问 Java-8 API 的情况下,我将编写适当的绑定(如有必要)以使用特定于语言的习语] 用那种语言感觉笨拙。
顺便说一句。我也会对在 Kotlin-Java 互操作上下文中对这个问题发表的任何评论感兴趣。
这个 Scala 程序演示了我的问题的一面,即如何让 Scala 函数伪装成 Java 8 个 Lambdas。
从语法和惯用的角度来看,这似乎可以通过创建一些隐式 Scala 函数将 Scala 函数转换为它们的 Java 8 FunctionalInterface 对应类型。
当然,需要注意的是,此方法没有利用 Java 8 通过 invokedynamic 优化 lambda 创建的能力。
因此,这种方法会导致为 Scala 函数实例创建 JVM 对象,与 Java 8 个本机 lambda 相比,这可能会影响内存使用和性能。
对于硬币的另一面,即如何让 Java 8 个 Lambda 伪装成 Scala 函数,我想必须编写一些 Java 代码才能与 Scala 互操作(如果一个人的目标是拥有一个可从 Java 调用的 Scala API)。
贾斯汀·约翰逊, 关于我的项目发条的微博, XPath/XQuery 在 JVM 上的新实现, 作为推特上的@MartianOdyssey
https://twitter.com/MartianOdyssey
/**
* Scala Functions masquerading as Java 8 Lambdas.
*
* (C) Justin Johansson 2015.
*
* Microblogging about my Project Clockwork, a
* new implementation of XPath/XQuery on the JVM,
* as @MartianOdyssey on Twitter (https://twitter.com/MartianOdyssey).
*
* Permission to use this code is granted under Apache License,
* Version 2.0 and providing attribution is afforded to author,
* Justin Johansson.
*/
package lab
import scala.language.implicitConversions
import java.util.{ Arrays => JArrays, List => JList }
import java.util.function.{ Consumer => JConsumer, Function => JFunction, Predicate => JPredicate }
import java.util.stream.{ Stream => JStream }
object JLambda extends App {
println("JLambda: Scala to Java 8 lambda test")
implicit def func1ToJConsumer[T](func: T => Unit): JConsumer[T] = {
new JConsumer[T] {
def accept(arg: T): Unit = func(arg)
}
}
implicit def func1ToJFunction[T, R](func: T => R): JFunction[T, R] = {
new JFunction[T, R] {
def apply(arg: T): R = func(arg)
}
}
implicit def func1ToJPredicate[T](func: T => Boolean): JPredicate[T] = {
new JPredicate[T] {
def test(arg: T): Boolean = func(arg)
}
}
val myList = JArrays.asList("cake", "banana", "apple", "coffee")
println(s"myList = $myList")
val myListFiltered: JStream[String] = myList.stream
.filter { x: String => x.startsWith("c") }
val myListFilteredAndMapped: JStream[String] = myListFiltered
.map { x: String => x.toUpperCase }
myListFilteredAndMapped.forEach { x: String => println(s"x=$x") }
}
/*
Outputs:
JLambda: Scala to Java 8 lambda test
myList = [cake, banana, apple, coffee]
x=CAKE
x=COFFEE
*/
btw. I would be interested in any comments with this question taken in a Kotlin-Java interop context also.
Kotlin 的 FunctionX
接口是 SAM 的,所以不需要做任何额外的事情来让 Java 8 理解它们