11

据我了解,Scala 中没有办法在匿名函数中有多个返回点,即

someList.map((i) => {
    if (i%2 == 0) return i // the early return allows me to avoid the else clause
    doMoreStuffAndReturnSomething(i) // thing of this being a few more ifs and returns
})

引发error: return outside method definition. (如果不提出这个问题,代码就不会像我希望的那样工作。)

我可以解决的一种解决方法如下

someList.map({
    def f(i: Int):Int = {
        if (i%2 == 0) return i
        doMoreStuffAndReturnSomething(i)
    }
    f
})

但是,我想知道是否有另一种“公认”的方式来做到这一点。也许有可能没有内部函数的名称?

continue(一个用例是在循环内模拟一些有价值的构造。)

编辑

请相信我,有必要避免使用 else 语句,因为该doMoreStuff部分实际上可能看起来像:

val j = someCalculation(i)
if (j == 0) return 8
val k = needForRecalculation(i)
if (k == j) return 9
finalRecalc(i)
...

当你只有一个if可用的 –<code>else 结构时,它很容易搞砸。

当然,在我一开始给出的简单示例中,使用else. 对不起,我以为这很清楚。

4

4 回答 4

6

如果您的匿名函数那么复杂,我会让它更明确。匿名函数不适合比几行更复杂的事情。您可以通过在 using 方法中声明它来使其成为私有方法

def myF(i:Int):Int = {
    if (i%2 == 0) return i
    doMoreStuffAndReturnSomething(i)
}
someList.map(myF(_))

这是您的解决方法的一种变体,但更简洁。他们都将其保持为本地方法范围的私有。

于 2010-05-24T17:41:19.637 回答
3

在您的代码注释中,您写道要避免使用该else关键字,但恕我直言,这正是您想要的,甚至更短了两个字符;-)

someList.map((i) => {
    if (i%2 == 0) i else
    doMoreStuffAndReturnSomething(i)
})
于 2010-05-24T17:43:36.487 回答
3

您给出的示例很容易通过 if 语句解决。这样做不会有任何表现或其他处罚。

但是你可能还有其他一些情况,看起来大致像

if (test) {
  if (anotherTest) {
    val a = someComputation()
    if (testOf(a)) return otherComputation()
  }
  else if (yetAnotherTest) return whatever()
}
bigComputation()

如果您想避免将其转换为不带返回的表单所需的 if 语句和/或代码重复的混乱,有几种方法可以处理这种情况。

你可以做各种偷偷摸摸的事情,Option或者Either让状态保持流动(orElsefold),这样你就只做你需要的计算。

你最好按照你的建议创建一个def。但只是为了比较,考虑一个 Option-wrapping 样式:

i => {
  ( if ((i%2)==0) Some(i) 
    else None
  ).getOrElse(doStuffAndReturn(i))
}

在上面的大例子中,这种风格会给

( if (test) {
    if (anotherTest) {
      val a = someComputation()
      if (testOf(a)) Some(otherComputation()) else None
    }
    else if (yetAnotherTest) Some(whatever())
    else None
}).getOrElse(bigComputation())

就个人而言,我不认为它更清晰(当然也不会更快),但这是可能的。

于 2010-05-24T18:28:37.563 回答
1

我认为匿名函数中返回点的主要问题是匿名函数可能会出现在通常不会出现的地方。因此,不清楚 return 语句实际上属于哪个闭包。这个问题是通过明确要求一个def-<code>return* 对应关系来解决的。

或者,人们需要围绕要返回的语句进行警卫。breakable—<code>break 但不幸的是无法返回值。一些基于延续的解决方案将能够实现该目标,但我想等待那里的一些普遍接受和库。

于 2010-08-13T18:29:45.567 回答