为什么在scala中使用返回一个坏习惯

时间:2014-05-05 19:54:11

标签: scala code-cleanup

我正在通过课程中的函数式编程课程进行学习。我注意到自动样式检查器告诉我使用' return'是一个坏习惯。这是为什么?对我而言,似乎使用return会使代码更具可读性,因为任何其他程序员都可以立即看到它以及函数返回的内容。

示例,为什么会这样;

def sum(xs: List[Int]): Int = {
    if( xs.length == 0){
      return 0
    }else{
      return xs.head + sum(xs.tail)
    }
}

被认为比这更糟糕;

def sum(xs: List[Int]): Int = {
    if( xs.length == 0){
      0
    }else{
      xs.head + sum(xs.tail)
    }
}

我习惯了javascript,所以这可能是我对此感到不安的原因。不过,任何人都可以明白为什么添加return语句会使我的代码变得更糟吗?如果是这样,为什么语言中有返回声明?

3 个答案:

答案 0 :(得分:9)

在Java中,Javascript和其他命令式语言if...else是一个流控制语句。

这意味着你可以这样做

public int doStuff(final boolean flag) {
    if(flag)
        return 1;
    else
        return 5;
}

但你不能这样做

public int doStuff(final boolean flag) {
    return if(flag)
        1;
    else
        5;
}

因为if...else语句而不是表达式。要实现这一点,您需要使用三元运算符(严格来说是"条件运算符"),如:

public int doStuff(final boolean flag) {
    return flag ? 1 : 5;
}

在Scala中,这是不同的。 if...else构造是一个表达式,因此更类似于您习惯使用的语言中的条件运算符。所以,事实上你的代码写得更好:

def sum(xs: List[Int]): Int = {
    return if(xs.length == 0) {
      0
    } else {
      xs.head + sum(xs.tail)
    }
}

此外,函数中的最后一个表达式会自动返回,因此return是多余的。事实上,由于代码只有单个表达式,大括号也是多余的:

def sum(xs: List[Int]): Int = 
    if(xs.length == 0) 0
    else xs.head + sum(xs.tail)

所以,回答你的问题:这是不鼓励的,因为如果Scala中的if...else构造是对性质的误解。

但除了这一点之外,你应该使用pattern matching

def sum(xs: List[Int]): Int = xs match {
   case Nil => 0
   case head::tail => head + sum(tail)
}

这更加惯用Scala。了解如何使用(和滥用)模式匹配,您将为自己节省巨大数量的代码行。

答案 1 :(得分:9)

我认为问题的另一个答案是

  

为什么在scala中使用返回一个坏习惯

是在闭包中使用时返回将从方法返回而不是从闭包本身返回。

例如,请考虑以下代码:

def sumElements(xs: List[Int]): Int = { 
  val ys: List[Int] = xs.map { x => 
    return x + 1
  }
  return ys.sum 
}

当使用sumElements(List(1, 2, 3, 4))调用此代码时,很容易错过,结果将是2而不是10。这是因为return中的map将从sumElements返回,而不是从map来回。

答案 2 :(得分:1)

在scala中,每一行都是expression,而不是statement。声明通常没有返回值,但表达式确实如此。

块的最后一个结果将是返回值,因此样式指南根据此假设进行操作。返回将是一个特殊的退出区块。

def sum(xs: List[Int]): Int = { if(xs.isEmpty) return 0 xs.head + sum(xs.tail) }

返回语句会导致函数在该返回时保释,并且通常会导致代码比使用if / else逻辑编写时更难以理解,就像之前所做的那样。我相信风格决策背后的理性是阻止这种类型的编程,因为它使程序更难理解。