kotlin语言
这篇文章最初发表在jooq.org上 ,这是一个博客,从jOOQ的角度着眼于所有开源,Java和软件开发。
您认为以下程序会打印什么?
fun main(args: Array) {
(1..5).forEach {
if (it == 3)
return
print(it)
}
print("done")
}
好吧……您可能猜错了。 上面将打印:
12
它不会打印出大多数人可能期望的内容:
1245done
请注意那些不感到惊讶的人:
上面对于习惯使用Java 8的人来说是特殊的,下面的代码确实可以打印1245done:
public static void main(String[] args) {
IntStream.rangeClosed(1, 5).forEach(it -> {
if (it == 3)
return;
System.out.print(it);
});
System.out.print("done");
}
语法原因在Kotlin手册的以下部分中进行了说明:
https://kotlinlang.org/docs/reference/returns.html
在lambdas / closures中,return语句不会(有必要)从lambda / closures中返回,而是从lambda / closures的直接封闭范围中返回。 JetBrains的Dmitry Jemerov在两则推文中向我提供了基本原理 :
@lukaseder @kotlin原因很简单:我们希望具有与内置语言功能完全一样的lambda(例如,已同步)
—德米特里·杰梅罗夫(@intelliyole) 2016年2月22日
@lukaseder因此,传递给“同步”功能的lambda中的“返回”必须与Java“同步”块中的“返回”相同
—德米特里·杰梅罗夫(@intelliyole) 2016年2月22日
为Java巧妙的Kotlin语言已经消除基于语言的支持结构,如try-with-resources
,或synchronized
语句。 这是非常合理的,因为这些语言结构不一定属于该语言( 正如我们先前在另一篇博客文章中所声称的那样 ),而是可以移至库中。 例如:
// try-with-resources is emulated using an
// extension function "use"
OutputStreamWriter(r.getOutputStream()).use {
it.write('a')
}
(这里的批评)
要么:
// Synchronized is a function!
val x = synchronized (lock, { computation() })
也可以看看:
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/synchronized.html
毕竟,即使在Java中,语言功能也只能起作用,因为该语言取决于库类型,例如Iterable (foreach)
, AutoCloseable (try-with-resources)
或JVM功能(监视每个引用上的synchronized
)。
那么,退货有什么用呢?
按照上述基本原理,当语言设计人员希望避免使用可通过库实现的事物构建语言构造,但仍希望您觉得它们是语言构造时,则返回这种“构造”内部的唯一合理含义-ish” lambda /闭包是从外部范围return
。 因此,当您编写如下内容时:
fun main(args : Array) {
val lock = Object()
val x = synchronized(lock, {
if (1 == 1)
return
"1"
})
print(x)
}
真正的意图是使它等效于以下Java代码:
public static void main(String[] args) {
Object lock = new Object();
String x;
synchronized (lock) {
if (1 == 1)
return;
x = "1";
}
System.out.println(x);
}
很明显,在Java情况下, return
语句退出main()
方法,因为没有其他合理的堆栈框架可从中返回。 与Kotlin不同,有人可能会说lambda /闭包将产生自己的堆栈框架。
但这确实不是。 原因是synchronized
函数上的inline
修饰符:
public inline fun <R> synchronized(lock: Any, block: () -> R): R {
monitorEnter(lock)
try {
return block()
}
finally {
monitorExit(lock)
}
}
也可以看看:
https://kotlinlang.org/docs/reference/inline-functions.html
这意味着作为参数传递的block
关闭实际上并不是纯粹的lambda表达式,而是嵌入在调用站点范围内的语法糖。
奇怪的。 狡猾。 聪明。 但是有点出乎意料。
这是一个好主意吗? 还是以后语言设计者会后悔? 所有的lambda /闭包是否都可能是“语言构造式的”,而期望这样的return语句会离开外部范围? 还是有明确的例子表明这种inline
行为完全有意义?
我们拭目以待。 在任何情况下,一种语言选择此路径都是非常有趣的。
翻译自: https://jaxenter.com/an-ingenious-workaround-to-emulate-sum-types-in-java-124244.html
kotlin语言
所有评论(0)