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在两则推文中向我提供了基本原理

为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语言

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐