6

为什么是

for (
  a <- 1 to 1000;
  b <- 1 to 1000 - a;
  c <- 1 to 1000 - a - b;
  if (a * a + b * b == c * c && a + b + c == 1000)
) println((a, b, c, a * b * c))

266 毫秒

那么慢:

for (a <- 1 to 1000)
  for (b <- 1 to 1000 - a)
    for (c <- 1 to 1000 - a - b)
      if (a * a + b * b == c * c)
        if (a + b + c == 1000)
          println((a, b, c, a * b * c))

62 毫秒

如果我理解正确,这应该是一样的吗?


处理答案后的解决方案:

for (
  a <- 1 to 1000;
  b <- 1 to (1000 - a)
) {
  val c = (1000 - a - b)
  if (a * a + b * b == c * c)
    println((a, b, c, a * b * c))
}

9 毫秒

4

2 回答 2

14

你的理解是错误的。

当条件在循环体中时会发生这种情况:

// this
for(x <- coll) if(condition) doSomething
// will translate to
coll.foreach{ x => if(condition) doSomething }

与条件在生成器本身时相反:

// this
for(x <- coll if(condition)) dosomething
// will translate to
coll.withFilter(x => condition).foreach{ x => dosomething }

您可以查看Scala 语言规范 6.16了解更多详细信息。

于 2013-02-28T14:04:47.917 回答
11

您可能需要查看此演示文稿(幻灯片 13-15)以了解有关如何在内部翻译 for 循环的详细信息。

您的示例的主要区别是:

  • for 循环体中的条件(2. 示例)
  • 生成器内的条件(1. 示例)

后者,也称为环路过滤,在设计上具有性能缺陷。为了极大地简化正在发生的事情:在内部withFilter(这是翻译的第一步),Function2[Object, Boolean]创建了一个匿名的新类型函数(用于评估条件)。传递给其apply函数的参数必须被装箱,因为它是基于Object. 这种装箱/拆箱比直接在 for 循环体中评估条件要慢得多if,它允许直接访问变量。

于 2013-02-28T14:06:15.370 回答