据我所知,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
- else
可用的结构很容易弄乱。
当然,在我刚开始给出的简单例子中,它更容易使用 else
。对不起,我觉得这很清楚。
如果你的匿名函数那么复杂,我会让它更明确。匿名函数不适用于比几行更复杂的东西。您可以通过在using方法中声明它来使其成为私有方法
def myF(i:Int):Int = {
if (i%2 == 0) return i
doMoreStuffAndReturnSomething(i)
}
someList.map(myF(_))
这是您的解决方法的变体,但更清洁。它们都将其保密为本地方法范围。
在您的代码注释中,您写道,您要避免使用 else
关键字,但恕我直言这完全是你想要的,它甚至两个字符更短;-)
someList.map((i) => {
if (i%2 == 0) i else
doMoreStuffAndReturnSomething(i)
})
您给出的示例很容易通过if语句解决。这样做没有表现或其他处罚。
但是你可能还有其他一些情况,看起来大致如此
if (test) {
if (anotherTest) {
val a = someComputation()
if (testOf(a)) return otherComputation()
}
else if (yetAnotherTest) return whatever()
}
bigComputation()
如果你想避免将if转换为没有返回的表单所需的if语句和/或代码重复的混乱,有几种方法可以处理这种情况。
您可以使用各种偷偷摸摸的东西 Option
要么 Either
保持国家流动(与... orElse
和 fold
)这样你只需要进行计算。
你建议你最好创建一个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())
就个人而言,我认为它更清晰(并且肯定不会更快),但它是可能的。
我认为匿名函数中返回点的主要问题是匿名函数可能会出现在通常不会期望它的地方。因此,不清楚返回语句实际上属于哪个闭包。通过明确要求a来解决这个问题 def
- return*
对应关系。
或者,人们需要围绕要返回的声明的警卫。 breakable
- break
但遗憾的是无法返回一个值。一些基于延续的解决方案将能够实现这一目标,尽管我想等待一些普遍的接受和库。