Scala的理解效率? [英] Scala for comprehension efficiency?

查看:87
本文介绍了Scala的理解效率?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在"Scala中的编程"一书的第23章中,作者举了一个示例:

In the book "Programming In Scala", chapter 23, the author give an example like:

case class Book(title: String, authors: String*)
val books: List[Book] = // list of books, omitted here
// find all authors who have published at least two books

for (b1 <- books; b2 <- books if b1 != b2;
    a1 <- b1.authors; a2 <- b2.authors if a1 == a2)
yield a1

作者说,这将翻译为:

books flatMap (b1 =>
   books filter (b2 => b1 != b2) flatMap (b2 =>
      b1.authors flatMap (a1 =>
        b2.authors filter (a2 => a1 == a2) map (a2 =>
           a1))))

但是,如果您查看地图和平面图方法定义( TraversableLike.scala ),您可能会发现,它们被定义为for循环:

But if you look into the map and flatmap method definition(TraversableLike.scala), you may find, they are defined as for loops:

   def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
    val b = bf(repr)
    b.sizeHint(this) 
    for (x <- this) b += f(x)
    b.result
  }

  def flatMap[B, That](f: A => Traversable[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
    val b = bf(repr)
    for (x <- this) b ++= f(x)
    b.result
  }

好吧,我想这for会不断转换为foreach,然后再转换为while语句,这是一个构造而不是表达式,scala没有for构造,因为它希望for总是产生一些东西.

Well, I guess this for will continually be translated to foreach and then translated to while statement which is a construct not an expression, scala doesn't have a for construct, because it wants the for always yield something.

因此,我想与您讨论的是,为什么Scala会这样做用于翻译"? 作者的示例使用了4个生成器,最后将其翻译成嵌套在4个级别的for循环,我认为books很大时,它的性能会非常糟糕.

So, what I want to discuss with you is that, why does Scala do this "For translation" ? The author's example used 4 generators, which will be translated into 4 level nested for loop in the end, I think it'll have really horrible performance when the books is large.

Scala鼓励人们使用这种语法糖",您总是可以看到大量使用过滤器,地图和平面图的代码,这似乎使程序员忘记了他们真正在做的事情是将一个循环嵌套在另一个循环中,以及达到的目的只是使代码看起来更短.你有什么想法

Scala encourage people to use this kind of "Syntactic Sugar", you can always see codes that heavily make use of filter, map and flatmap, which seems programmers are forgetting what they really do is nesting one loop inside another, and what achieved is only to make codes looks a bit shorter. What's your idea?

推荐答案

对于理解而言,它是用于单子转换的语法糖,因此,在各种场合都非常有用.那时,它们在Scala中比等效的Haskell构造更为冗长(当然,Haskell默认情况下是非严格的,因此不能像Scala那样谈论该构造的性能).

For comprehensions are syntactic sugar for monadic transformation, and, as such, are useful in all sorts of places. At that, they are much more verbose in Scala than the equivalent Haskell construct (of course, Haskell is non-strict by default, so one can't talk about performance of the construct like in Scala).

同样重要的是,此构造可以使所做的工作保持清晰,并避免快速升级缩进或不必要的私有方法嵌套.

Also important, this construct keeps what is being done clear, and avoids quickly escalating indentation or unnecessary private method nesting.

关于最后的考虑,无论是否掩盖了复杂性,我都会假设:

As to the final consideration, whether that hides the complexity or not, I'll posit this:

for {
  b1 <- books
  b2 <- books
  if b1 != b2
  a1 <- b1.authors
  a2 <- b2.authors 
  if a1 == a2
} yield a1

很容易看到正在执行的操作,并且很清楚:复杂度:b ^ 2 * a ^ 2(过滤器不会改变复杂度),适用于书籍数量和作者数量.现在,使用深度缩进或私有方法用Java编写相同的代码,并尝试快速确定代码的复杂性.

It is very easy to see what is being done, and the complexity is clear: b^2 * a^2 (the filter won't alter the complexity), for number of books and number of authors. Now, write the same code in Java, either with deep indentation or with private methods, and try to ascertain, in a quick look, what the complexity of the code is.

因此,恕我直言,这并没有掩盖复杂性,相反,它却使事情变得清晰起来.

So, imho, this doesn't hide the complexity, but, on the contrary, makes it clear.

至于您提到的map/flatMap/filter定义,它们不属于List或任何其他类,因此不会应用.基本上,

As for the map/flatMap/filter definitions you mention, they do not belong to List or any other class, so they won't be applied. Basically,

for(x <- List(1, 2, 3)) yield x * 2

被翻译成

List(1, 2, 3) map (x => x * 2)

那和

map(List(1, 2, 3), ((x: Int) => x * 2)))

这是调用您传递的定义的方式.作为记录,在Listmap的实际实现是:

which is how the definition you passed would be called. For the record, the actual implementation of map on List is:

def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
  val b = bf(repr)
  b.sizeHint(this) 
  for (x <- this) b += f(x)
  b.result
}

这篇关于Scala的理解效率?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆