我是一个新手scala程序员,并遇到了一个奇怪的行为。
def balanceMain(elem: List[Char]): Boolean =
{
if (elem.isEmpty)
if (count == 0)
true;
else false;
if (elem.head == '(')
balanceMain(elem.tail, open, count + 1);....
上面基本上我想要返回true如果elem.isEmpty
和count == 0
。否则,我想返回false。
现在我已经读过,不需要在scala中添加return语句。所以我上面省略了return
。但它不返回布尔值。如果我添加一个返回语句为return true
。它完美地运作。为什么会这样?
另外,为什么在scala中使用return语句被认为是一种不好的做法
这并不像省略return
关键字那么简单。在Scala中,如果没有return
,那么最后一个表达式将被视为返回值。因此,如果最后一个表达式是您想要返回的,那么您可以省略return
关键字。但是如果你想要返回的内容不是最后一个表达式,那么Scala就不会知道你想要返回它。
一个例子:
def f() = {
if (something)
"A"
else
"B"
}
函数f
的最后一个表达式是if / else表达式,其求值为String。由于没有标记明确的return
,Scala会推断您想要返回此if / else表达式的结果:String。
现在,如果我们在if / else表达式之后添加一些内容:
def f() = {
if (something)
"A"
else
"B"
if (somethingElse)
1
else
2
}
现在,最后一个表达式是一个if / else表达式,其值为Int。所以f
的返回类型将是Int。如果我们真的希望它返回String,那么我们就会遇到麻烦,因为Scala不知道那是我们的意图。因此,我们必须通过将String存储到变量并在第二个if / else表达式之后返回它,或者通过更改顺序以使String部分最后发生来修复它。
最后,即使使用像你这样的嵌套if-else表达式,我们也可以避免使用return
关键字:
def f() = {
if(somethingFirst) {
if (something) // Last expression of `if` returns a String
"A"
else
"B"
}
else {
if (somethingElse)
1
else
2
"C" // Last expression of `else` returns a String
}
}
到目前为止,这个主题实际上有点复杂。这个blogpost by Rob Norris更详细地解释了它,并举例说明何时使用return实际上会破坏你的代码(或者至少有非明显的效果)。
在这一点上,让我引用帖子的精髓。最重要的陈述恰好在一开始。将此打印为海报并将其放在墙上:-)
return
关键字不是“可选的”或“推断的”;它改变了程序的含义,你永远不应该使用它。
它给出了一个例子,当你内联函数时,它实际上会破坏某些东西
// Inline add and addR
def sum(ns: Int*): Int = ns.foldLeft(0)((n, m) => n + m) // inlined add
scala> sum(33, 42, 99)
res2: Int = 174 // alright
def sumR(ns: Int*): Int = ns.foldLeft(0)((n, m) => return n + m) // inlined addR
scala> sumR(33, 42, 99)
res3: Int = 33 // um.
因为
在评估时,
return
表达式放弃当前计算并返回到return
出现的方法的调用者。
这只是链接帖子中给出的一个例子,它是最容易理解的。还有更多,我非常鼓励你,去那里,阅读和理解。
当你来自像Java这样的命令式语言时,这一开始可能看起来很奇怪,但是一旦你习惯了这种风格它就会有意义。让我结束另一个引用:
如果您发现自己处于想要提前返回的状态,则需要重新考虑定义计算的方式。
我不编写Scala程序,但我使用另一种隐式返回语言(Ruby)。在if (elem.isEmpty)
块后面有代码 - 最后一行代码是返回的,这就是为什么你没有得到你期望的。
编辑:这是一个更简单的编写函数的方法。只需使用isEmpty的布尔值并计数自动返回true或false:
def balanceMain(elem: List[Char]): Boolean =
{
elem.isEmpty && count == 0
}
默认情况下,将返回函数的最后一个表达式。在您的示例中,在该点之后还有另一个表达式,您需要返回值。如果你想在最后一个表达式之前返回任何内容,你仍然需要使用return
。
您可以像这样修改您的示例,从第一部分返回Boolean
def balanceMain(elem: List[Char]): Boolean = {
if (elem.isEmpty) {
// == is a Boolean resulting function as well, so your can write it this way
count == 0
} else {
// keep the rest in this block, the last value will be returned as well
if (elem.head == "(") {
balanceMain(elem.tail, open, count + 1)
}
// some more statements
...
// just don't forget your Boolean in the end
someBoolExpression
}
}
如果没有相应的if
,请不要写else
语句。一旦你将else
添加到你的片段,你就会发现你的true
和false
实际上是函数的最后一个表达式。
def balanceMain(elem: List[Char]): Boolean =
{
if (elem.isEmpty)
if (count == 0)
true
else
false
else
if (elem.head == '(')
balanceMain(elem.tail, open, count + 1)
else....
用例匹配用于提前退货。它将强制您明确声明所有返回分支,防止忘记在某处写入返回的粗心错误。