Scala 匿名函数中的返回语句 [英] Scala return statements in anonymous functions

查看:24
本文介绍了Scala 匿名函数中的返回语句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么匿名函数中的显式返回语句(使用 return 关键字)从封闭的命名函数返回,而不仅仅是从匿名函数本身返回?

Why does an explicit return statement (one that uses the return keyword) in an anonymous function return from the enclosing named function, and not just from the anonymous function itself?

例如以下程序导致类型错误:

E.g. the following program results in a type error:

def foo: String = {
  ((x: Integer) => return x)
  "foo"
}

我知道建议避免使用 return 关键字,但我感兴趣的是为什么显式和隐式 return 语句在匿名函数中具有不同的语义.

I know it's recommended to avoid the return keyword, but I'm interested in why the explicit and implicit return statements have a different semantics in anonymous functions.

在以下示例中,返回语句在 m 执行完毕后存活",程序导致运行时异常.如果匿名函数没有从封闭函数返回,则无法编译该代码.

In the following example, the return statement "survives" after m has finished executing, and the program results in a run-time exception. If anonymous functions didn't return from the enclosing function, it would not be possible to compile that code.

def main(args: Array[String]) {
  m(3)
}

def m: (Integer => Unit) =
  (x: Integer) => return (y: Integer) => 2

推荐答案

正式来说return定义为总是从最近的封闭命名方法返回

Formally speaking return is defined as always returning from the nearest enclosing named method

返回表达式 return e 必须出现在 some 的主体内封闭命名的方法或函数.最里面的封闭命名源程序中的方法或函数 f 必须具有显式声明的结果类型,并且 e 的类型必须符合它.回报表达式计算表达式 e 并将其值作为f 的结果.任何语句或表达式的评估后面的返回表达式被省略.

A return expression return e must occur inside the body of some enclosing named method or function. The innermost enclosing named method or function in a source program, f , must have an explicitly declared result type, and the type of e must conform to it. The return expression evaluates the expression e and returns its value as the result of f . The evaluation of any statements or expressions following the return expression is omitted.

所以它在 lambda 中没有不同的语义.问题是,与普通方法不同,从 lambda 创建的闭包可以逃避对封闭方法的调用,并且如果在这样的闭包中有返回,您可能会得到异常.

So it doesn't have different semantics in a lambda. The wrinkle is that, unlike a normal method, a closure created from a lambda can escape a call to the enclosing method and you can get an exception if there is a return in such a closure.

如果返回表达式本身是匿名函数的一部分,它f 的封闭实例可能已经返回在执行返回表达式之前.在这种情况下,抛出scala.runtime.NonLocalReturnException 不会被捕获,并且会向上传播调用堆栈.

If the return expression is itself part of an anonymous function, it is possible that the enclosing instance of f has already returned before the return expression is executed. In that case, the thrown scala.runtime.NonLocalReturnException will not be caught, and will propagate up the call stack.

现在,至于为什么".一个较小的原因是美学:lambdas 是表达式,当一个表达式及其所有子表达式具有相同的含义时,无论嵌套结构如何,这都很好.Neal Gafter 在 http://gafter.blogspot.com 上谈到了这一点/2006/08/tennents-correspondence-principle-and.html

Now, as for "why". One lesser reason is aesthetic: lambdas are expressions and it's nice when an expression and all its subexpression have the same meaning no matter what the nesting structure. Neal Gafter talks about that at http://gafter.blogspot.com/2006/08/tennents-correspondence-principle-and.html

不过,它存在的主要原因是它允许您轻松模拟命令式编程中常用的控制流形式,但仍允许您将事物抽象为更高阶的函数.作为一个玩具示例,Java 的 foreach 构造 (for (x : xs) { yada; }) 允许在循环内返回.Scala 没有语言级别的 foreach.相反,它将 foreach 放入库中(不计算没有 yield 的for expression",因为它们只是对 foreach 脱糖).具有非本地返回意味着您可以采用 Java foreach 并直接转换为 Scala foreach.

The main reason it exists, though, is it allows you to easily simulate forms of control flow commonly used in imperative programming but still allows you to abstract things into higher order functions. As a toy example, Java's foreach construct (for (x : xs) { yada; }) allows a return inside the loop. Scala doesn't have a language level foreach. Instead, it puts foreach in the library (not counting "for expression" without yield since they just desugar to foreach). Having a non-local return means you can take a Java foreach and translate directly to a Scala foreach.

顺便说一句,Ruby、Smalltalk 和 Common Lisp(我想不到)也有类似的非本地"返回.

BTW, Ruby, Smalltalk, and Common Lisp (off the top of my head) also have similar "non-local" returns.

这篇关于Scala 匿名函数中的返回语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆