scala - Scala 如何实现从表达式中返回?

标签 scala return implementation anonymous-function

例如,如果我们有一个类似的方法

def find[A](xs: Seq[A], p: A => Boolean): Option[A] = {
  xs.foreach(x => if (p(x)) return Some(x));
  None;
}

(当然有一个库函数,这只是一个例子)。执行如何逃逸foreach当内部函数return年代?

或在
def foo(x: AnyRef): String =
  process(x match {
    case (s: String) => s;
    case _           => return "";
  })

执行如何避免运行processreturn ""发行?

最佳答案

foo示例取决于哪个

def process(s: String): String
def process(s: => String): String

它是。我假设是前者,因为你建议 process没有运行。这正是传递参数时始终工作的方式——你首先进行参数创建工作,然后调用方法。既然你遇到了 return ,很简单:您只需调用相应的return在创建参数*时从字节码中提取,并且永远不要继续调用该方法。所以这只是局部返回。
find示例涉及更多。让我们尝试一个由 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 block 保证捕获它),它并没有那么糟糕 - 与调用 trig 函数或求和一样糟糕包含几十个条目的数组。

另请注意 pr在异常得到它之前只被部分执行。在这种情况下,它不会打印任何内容,因为它所做的第一件事是尝试使用 s填写一个实际的字符串,但随后会遇到异常,将控制权返回到 foo . (所以你从 foo 得到一个空字符串,但你不打印任何东西。)

* 实际上,在字节码中,它往往是到方法末尾的跳转,在那里加载/返回。不过,在概念上无关紧要。

关于scala - Scala 如何实现从表达式中返回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17704050/

相关文章:

scala - 如何在 Spark ML 中使用 CountVectorizer 计算单词的频率?

c++ - 使用一对作为另一个函数的参数

return - 如何跳出 Lisp 中的函数?

scala - 为什么在返回语句后没有死代码警告?

c++ - OpenCV : Object detection and tracking based on feature detection

algorithm - O(|V|^2) 中 Prim 的 MST 算法

具有数组性能的 Scala 操作(scalacl 插件)

scala - 如何将 Seq[Try] 转换为 Try[Seq]

scala - akka actor 中的增量处理

c++ - 如何使用链表节点修改另一个链表