什么是非本地回报?

时间:2012-01-17 15:45:43

标签: function programming-languages

什么是非本地回报?在什么情况下它是有用的?请举例说明。

3 个答案:

答案 0 :(得分:11)

Here's a good article关于在ruby块的上下文中使用非本地返回。

  

Ruby的块支持非本地返回(一些引用),这意味着   从块返回的行为与从返回的行为相同   块的原始背景。

它基本上意味着你可以从一个函数调用一个块,并且该块能够从原始函数返回。

答案 1 :(得分:5)

这意味着退出函数并在调用函数的位置之外的其他位置结束。它主要用于引用例外(即Java和C ++中的trythrowcatch,但它也可能意味着{{{} 1}}在C。

答案 2 :(得分:0)

这里要解释的是一些示例代码,以解释什么是非本地返回。

object Scratch {
    def foo: Int = {
        val list = List(1, 2, 3, 4)
        list.foreach { each =>
            if(each > 2) {
                return each // NLR
            }
            println(each)
    }
    return 5   
}


def main(args : Array[String]) : Unit = {
    val i = foo
    println("i: " + i)   
}

上面的代码在Scala中,但是对于其他任何支持非本地返回的语言(例如Kotlin以及最著名的Smalltalk和Ruby),事情也将是必不可少的(我也认为大多数功能性编程语言以及List也是如此)

这里要指出的是,上面的代码会将此输出写入控制台:

1
2
i: 3

因此,它也不会在控制台上同时显示4和5,这与不支持闭包内部非本地返回的语言有很大的区别。

在上面的代码段中,“ NLR”行的返回从闭包>>和<<退出调用该闭包的函数。这是与本地返回不同的地方,本地返回将从闭包中返回,但是此后执行将在闭包之后的下一行以调用闭包的相同方法继续执行。从这个意义上说,非本地收益不再是本地收益,而是“超级”本地收益。但是,它又被称为非本地收益。

在没有非本地返回的语言(例如Java或C#)中,上述代码将被编译器拒绝。在Java中,lambda内部的纯返回(只是返回而没有返回值)与continue具有相同的效果。

非本地返回会花费一些额外的CPU时间(据我所知很少),但还会导致在堆上进行分配,因为带有非本地返回的闭包无法再在堆栈上分配。这是因为这样的闭包可以传递给其他函数(也可能在其他线程中)。因此,支持非本地返回的闭包会消耗更多的堆空间。

当从闭包传递到的函数完成非本地返回时,执行线程跳出该函数,如此处的示例代码所示。我认为这就是许多函数式编程语言支持非本地返回的原因,因为将函数作为参数传递给其他函数是函数式编程中一种常见的处理方式。

为什么非本地返回问题?因为您希望能够从闭包中退出,就像从for循环或while循环或普通函数中一样。如果对于闭包是不可能的,那么一旦需要使用for或while循环完成一些非本地返回,则必须重新编写以闭包开始的整个代码。那样的话,闭包的表现力就会丧失。