如何避免return语句和for循环中的转义?

时间:2014-12-27 23:49:20

标签: scala functional-programming

我被告知要避免在Scala中使用return,尽管我不确定原因。

我有以下代码,它似乎没有返回正确的东西除非我把return关键字放在那里。为什么我需要放return

def nextParen(chars: List[Char]): List[Char] =
  for(i <- 0 to chars.size - 1) {
    if(chars(i) == '(' || chars(i) == ')') {
      return chars.slice(i, chars.size)  // return HERE!
    }
  }
  List.empty
}

3 个答案:

答案 0 :(得分:7)

避免return的论点是,它会导致代码的可读性降低,而不是重构安全。如果您找到一种最佳表达方式的算法,那么这不是一个绝对的规则,但通常可以通过将其编写为表达式来使代码更清晰。

此特定代码看起来等同于:

def nextParen(chars: List[Char]) =
  chars.dropWhile{c => c != '(' && c != ')'}

一般来说,尝试专注于编写表达式而不是程序;而不是告诉编译器它应该采取什么步骤,告诉它值是什么。即使你不了解dropWhile,你也可以将循环写成折叠(例如foldLeft),说明在列表的每个元素上做什么,然后是list最后是空的,会自然而然地出现,而不是需要两个不同的分支,以便有匹配的地方和没有的地方。

答案 1 :(得分:2)

当使用return明确表达您对良好算法的意图时,没有任何问题。但是,您应该谨慎使用它,因为它没有必要,并且您想要做的大多数事情已经在集合库中具有不错的实现。

因此,例如,您的代码可以工作,但是O(n^2)的大小与列表大小相同,因为您正在索引为线性数据结构。使用

要好得多
chars.dropWhile(c => c != '(' && c != ')')

或者如果您对此不了解,可以使用大量替代方案:

val i = chars.indexWhere(c => c == '(' || c == ')')
if (i < 0) chars take 0 else chars drop i

var found = false
chars.filter(c => found || { found = (c == '(' || c == ')'); found })

你可以拿出六打而不用太努力。 (使用指示符折叠,使用if子句,跨度等获得/ yield)。

因此,不使用return的最佳理由是您应该了解您的图书馆。通常你不需要它;最好使用计算你想要的股票方法。

答案 2 :(得分:1)

您在上面的命令意义上使用了for。如果您在更实用的意义上使用回报,即for-yieldfoldtakeWhile,则不必使用回报。

我认为当你从命令式转变为功能性(无副作用)时,最重要的事情之一就是你可以用一系列表达式来表达你的代码。其中的计算结果为。例如,for-yield表达式的计算结果为value。因此,在命令式世界中,您正在执行一系列语句,这些语句正在改变您周围的状态(数据结构,控制台等)。

PS:我已经使用了许多新的Scala程序员可能听不到的术语(例如,副作用,for-yield,value)。但凭借更多的经验,他们会更有意义。我强烈推荐这本书 - Structure and Interpretation of Computer Programs