4

scala 中“高级迭代”的最佳风格是什么?在哪些情况下我应该使用理解,以及何时我应该寻找替代的迭代方式(就风格而言)。在Programming in Scala书中有一个看起来几乎和下一个例子一样的例子:

for{
    file <- filesHere
    if file.getName.endsWith("txt")
    line <- Source.fromFile(file).getLines.toList
    if line.trim.matches(pattern)
  } println("|" + file + ": " + line.trim)

我尝试使用内部迭代重写它并得到:

filesHere foreach { file =>
  if (file.getName.endsWith("txt")) {
    Source.fromFile(file).getLines.toList foreach {line =>
      if (line.trim.matches(pattern)) println("|" + file + ": " + line.trim)
    }
  }
}   

但是,在网上(包括stackoverflow)我发现很多文章/帖子说服使用理解,我觉得使用它不方便。恕我直言,内部迭代更具可读性和方便性。

关于这个主题的最佳指南是什么?

4

2 回答 2

3

我认为你正在学习 Scala 很棒。它背后有一个很棒的社区,非常活跃,我认为随着时间的推移,你会对你的决定越来越满意。

至少就目前而言,我认为您应该坚持使用“Scala 编程”,因为它写得非常好,并且是对这门语言的精彩介绍。然后,一个很好的地方是 Scala api 文档本身,因为许多类/方法都包含示例代码。此外,谷歌小组非常活跃(正如我所说,那里的人非常友好)。

请记住,您作为示例提供的代码不返回任何值,而只是产生副作用(在 Java 中,这将有一个void返回值)。大多数 Scala API 都针对几乎没有返回值的副作用的函数(例如,您可能有日志记录的副作用,但惯用的 scala 代码将最大限度地减少方法和函数的副作用)。

在 Scala API 中,如果符合您的需要,有些方法将是首选样式。例如,在 Scheme 中你可能会做一个内部循环来迭代,在 Scala 中它可能看起来像这样:

val myScores = List(4, 8, 6, 1, 2, 4, 9, 8)

def max(ls: List[Int]): Int = {
  def iter(acc: Int, rem: List[Int]): Int = {
    if (rem.isEmpty) acc
    else if (rem.head > acc) iter(rem.head, rem.tail)
    else iter(acc, rem.tail)
  }
  iter(ls.head, ls)
}

但我不需要编写该函数,因为max列表 API 中已经实现:

myScores.max

所以,如果你想做的事情已经被一个库实现了,你应该使用它。max()是一个简单的例子,但在 Scala API 中可以找到更复杂的转换,并且scalaz

A for-comprehension(您帖子的原始主题)是flatMapmap和. 的组合filter。如果您正在做一些相当简单的事情,那么两个版本都将具有同样的可读性,但如果您正在做一长串flatMap,mapfilter串在一起以创建一个复杂的转换,那么for-comprehension 将更具可读性。

编辑:

具体到您的问题,我认为for-comprehension 版本更易于阅读:

val filterMapFlatmapVersion: List[String] = 
  fileNames.filter(_.endsWith("txt")).flatMap { file =>
    io.Source.fromFile(file).getLines().toList.map(_.trim).filter(_ == pattern)
}

val forVersion: List[String] =
  for {
    fileName <- fileNames
    if fileName.endsWith("txt")
    line <- io.Source.fromFile(fileName).getLines()
    if line.trim().matches(pattern)
  } yield line.trim
于 2013-09-18T17:02:32.193 回答
1

我希望理解成为 Scala 中的首选方法。值得注意的是 for-comprehension 实际上是 a mapand的语法糖filter

于 2013-09-18T16:26:11.760 回答