Scala样式:适用于vs foreach,过滤器,地图等 [英] Scala style: for vs foreach, filter, map and others
问题描述
在scala中,最好的样式是高级迭代"而不是smth集合.在哪种情况下,我应该使用理解方法,何时应该寻找替代的迭代方式(就样式而言).在 Scala中的编程
书中,有一个示例几乎像下一个示例:
What is the best style in scala for "advanced iteration" over collection of smth. In which cases I should use for-comprehension and when I should look for alternative way(in terms of style) of iteration. In Programming in Scala
book there is an example that looks almost as next one:
for{
file <- filesHere
if file.getName.endsWith("txt")
line <- Source.fromFile(file).getLines.toList
if line.trim.matches(pattern)
} println("|" + file + ": " + line.trim)
我尝试使用内部迭代重写它并得到:
I've tried to rewrite it using internal iteration and got:
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),我发现有许多说服性的文章/帖子可用于理解,但我觉得使用起来并不方便.恕我直言,内部迭代非常容易阅读和方便.
However, on the web(including stackoverflow) I've found a lot of articles/posts persuading to use for-comprehension, I don't find it convenient for me to use it. IMHO, internal iteration is much readable and convenient.
关于此主题的最佳指导是什么?
What are the best guidelines on this topic?
推荐答案
我认为您正在学习Scala真是太好了.背后有一个很棒的社区,非常活跃,我认为随着时间的流逝,您对自己的决定会越来越满意.
I think it is great that you are learning Scala. There is a wonderful community behind it, very active, and I think that you'll be more-and-more pleased with your decision as time goes on.
至少目前来说,我认为您应该坚持"Scala编程",因为它写得很好,并且对语言有很棒的介绍.然后,Scala api文档本身就是一个不错的选择,因为许多类/方法都包含示例代码.另外,Google小组非常活跃(正如我所说,那里的人非常友好).
For the moment, at least, I think that you should stick to "Programming in Scala" as it is very well written and a terrific introduction to the language. Then, a good place to look will be the Scala api docs themselves as many of the classes/methods contain sample code. Also, the google group is very active (and, as I said, the people there are very friendly).
请记住,作为示例提供的代码不返回任何值,而只是产生副作用(在Java中,这将具有 void
返回值).大多数Scala API都围绕着具有返回值的副作用的函数(例如,您可能会有日志记录的副作用,但是惯用的Scala代码将使方法和函数的副作用最小化).
Keep in mind that the code you provide as an example returns no value, but rather just gives side-effects (in Java, this would have a void
return value). Most of the Scala API is geared around functions with little to no side-effects that return a value (you might have, for example, a side-effect of logging, but idiomatic scala code will minimize side-effects in methods and functions).
在Scala API中,有一些方法可以满足您的需求(如果需要的话).例如,在Scheme中,您可以执行一个内部循环来进行迭代,在Scala中,它可能看起来像这样:
Within the Scala API, there are methods that would be the preferred style, if it matches your need. For example, in Scheme you might do an inner loop to iterate, in Scala it might look like this:
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中实现:
But I don't need to write that function because max
is already implemented in the list API:
myScores.max
因此,如果您要执行的操作已由库实现,则应使用该库. max()
是一个简单的示例,但是在Scala API和 scalaz
So, if what you want to do is already implemented by a library, you should use that. max()
is a trivial example, but there are much more complex transformations to be found in the Scala API and scalaz
用于理解的(您帖子的原始主题)是
flatMap
, map
和 filter
.如果您做的事情相当简单,那么两个版本的可读性都一样,但是如果您要编写一长串的 flatMap
, map
和 filter
串在一起创建一个复杂的转换,那么 for
-comprehension将更易读.
A for
-comprehension (the original topic of your post) is a combination of flatMap
, map
, and filter
. If you are doing something fairly simple, then both versions will be just as readable, but if you are doing a long chain of flatMap
, map
, and filter
strung together to create a complex transformation, then a for
-comprehension will be more readable.
针对您的问题,我认为 for
-理解版本更容易阅读:
Specific to your question, I think the for
-comprehension version is easier to read:
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
这篇关于Scala样式:适用于vs foreach,过滤器,地图等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!