为什么lambda无法使封闭函数返回?

时间:2019-02-19 13:23:51

标签: function lambda kotlin anonymous-function

我对Kotlin很陌生。我在浏览文档时碰到了这一部分:

  

“ lambda无法从封闭函数返回”(除非已内联)。

所以,这不起作用;

window.scroll({
  top: 2500, 
  left: 0, 
  behavior: 'smooth' <pre rel="HTML"><code markup="tt" class="language-markup">
});

// Scroll certain amounts from current position 
window.scrollBy({ 
  top: 100, // could be negative value
  left: 0, 
  behavior: 'smooth' 
});

// Scroll to a certain element
document.querySelector('.hello').scrollIntoView({ 
  behavior: 'smooth' 
});

我想知道为什么会这样吗?

我唯一想到的是危险的,因为在执行lambda之后,封装函数可能会做一些额外的事情。但是我不确定这是为什么,因为您可以通过使用合格的收益或使用fun foo() { ordinaryFunction { return // ERROR: cannot make `foo` return here } } 关键字来克服这一问题。因此,这种暗示背后有一个技术原因(除了任何可用性/安全性原因之外),就像编译器无法确定返回的位置,除非它被标记或内联。

任何帮助都会很棒!

3 个答案:

答案 0 :(得分:2)

这里的问题是non-local返回can't be done on the JVM。 如果要从lambda返回(本地返回),则可以添加标签@ordinaryFunction

fun foo() {
    ordinaryFunction {
        return@ordinaryFunction
    }
}

Docs说:

  

如果需要从lambda表达式返回,则必须标记它并限定return。通常,使用隐式标签会更方便:这样的标签与lambda传递给的函数同名。在我们的例子中是@ordinaryFunction

答案 1 :(得分:1)

其他人可能可以更好地解释这一点,但是几乎在任何编程语言中,调用函数时,都会在堆栈的顶部创建一个新条目。堆栈保留有关调用函数的参数以及函数完成时应返回的位置的信息。

Kotlin没有一项功能可让您一次返回多个函数调用,因此您必须手动从每个函数调用返回。

当内联函数时,通常将在单独的子例程中执行的机器代码现在复制粘贴到函数调用站点。这就是为什么从内联函数返回实际上是从称为内联lambda的函数返回的原因。

答案 2 :(得分:0)

  

lambda执行后,封装函数可能还会做一些额外的事情。

问题是相反的:lambda可以从封闭函数的作用域中“逃脱”,并在函数返回后最终执行。例如。考虑

fun foo() {
    Thread(Runnable { 
        Thread.sleep(1000)
        return
    })
}

或者只是

 fun foo() = // lambda

在任何一种情况下,lambda从foo返回都是没有意义的吗?而且编译器不知道您的ordinaryFunction是否让lambda逃脱foo的范围,除非它是内联的。

  

您可以通过使用合格的回报来克服这一问题

这并没有真正克服,只是没有从封闭函数中返回。