该foo
示例取决于哪个
def process(s: String): String
def process(s: => String): String
这是。我假设前者,因为你建议process
没有运行。这正是传递参数时它始终工作的方式——你首先进行参数创建工作,然后调用该方法。由于您遇到 a return
,这很容易:您只需return
在创建参数*时从字节码调用适当的,而永远不要继续调用该方法。所以这只是局部回报。
这个find
例子涉及更多一点。让我们尝试一个由 a 驱动的最简单的示例,foo
该示例需要非本地返回:
class Nonlocal {
def pr(s: => String) = { println(s); "Printed" }
def foo(x: AnyRef): String = pr(x match {
case (s: String) => s;
case _ => return "";
})
}
的主体foo
相当于
import scala.runtime.NonLocalReturnControl
val temp = new AnyRef
try {
pr(x match {
case s: String => s
case _ => throw new NonLocalReturnControl(temp, "")
})
}
catch {
case nlrc: NonLocalReturnControl[_] if (nlrc.key eq temp) =>
nlrc.value.asInstanceOf[String]
}
需要注意的关键事情是创建了一个哨兵对象,以便这些东西可以任意嵌套而不会相互破坏,并且可以NonLocalReturnControl
返回正确的值。毫不奇怪,与仅仅返回一个Int
. 但是由于它创建了一个没有堆栈跟踪的异常(安全,因为它无法逃脱:catch
保证该块可以捕获它),它并没有那么糟糕 - 与调用 trig 函数或用 a 对数组求和一样糟糕几十个条目。
另请注意,在异常获取之前pr
仅部分执行。在这种情况下,它不会打印任何内容,因为它所做的第一件事是尝试使用s
来填充实际的字符串,但随后它会遇到异常,将控制权放回foo
. (所以你从 得到一个空字符串foo
,但你不打印任何东西。)
*实际上,在字节码中,它往往是到方法末尾的跳转,在那里加载/返回。不过,在概念上无关紧要。