Stream 导致 Scala 中的内存不足错误



当我使用列表时,它可以正常工作,但是当我创建一个无限的流时

def foo = {
    val s = Stream.from(1)
    s.flatMap(x =>
                s.flatMap(y =>
                    s.flatMap(z => f(x, y, z))))
}

当我调用时,我收到一个java.lang.OutOfMemoryError。

foo.take(10)

关于 f

    def f(x: Int, y: Int, z: Int) = {
       if(Math.pow(x, 2) + Math.pow(y, 2) == Math.pow(z, 2) )
       else None
    }
最初,我

以为只有当我为这 10 个元素调用它时才会被评估,但我知道我不确定。我在Iterator.from(1)遇到了同样的问题请帮忙。提前谢谢你!

看起来您正在尝试生成第一个成员大于第二个成员的三元组。 首先,让我们生成一些这样的对:

scala> def natNums = Iterator from 1
natNums: Iterator[Int]
scala> def foo = for { x <- natNums; y <- 1 until x } yield (x,y)
foo: Iterator[(Int, Int)]
scala> (foo take 15).toList
res4: List[(Int, Int)] = List((2,1), (3,1), (3,2), (4,1), (4,2), (4,3), (5,1), (5,2), (5,3), (5,4), (6,1), (6,2), (6,3), (6,4), (6,5))

我走在正确的轨道上吗?

好的,现在您要向元组添加第三个成员。 好吧,如果我们类似地将 z 约束为小于 y,它就可以正常工作:

scala> def foo = for { x <- natNums; y <- 1 until x; z <- 1 until y } yield (x,y,z)
foo: Iterator[(Int, Int, Int)]
scala> (foo take 15).toList
res1: List[(Int, Int, Int)] = List((3,2,1), (4,2,1), (4,3,1), (4,3,2), (5,2,1), (5,3,1), (5,3,2), (5,4,1), (5,4,2), (5,4,3), (6,2,1), (6,3,1), (6,3,2), (6,4,1), (6,4,2))

但是如果 z 不受约束,我不明白您希望程序做什么。 只需从natNums中绘制z,就可以将CPU变成烤面包机:

scala> def foo = for { x <- natNums; y <- 1 until x; z <- natNums } yield (x,y,z)
foo: Iterator[(Int, Int, Int)]
scala> (foo take 15).toList
^C

你能给我们你期望的输出吗?

更新:啊! 毕达哥拉斯三元组——多么有趣!

这是一个简单的生成器,我称之为"原始"毕达哥拉斯三元组,因为它包含需要过滤掉的倍数。 例如,(6,8,10) 不应算作毕达哥拉斯三元组,因为它是 (3,4,5) 的倍数。 我会把它留给你,因为我认为阻碍你的只是首先生成数字的部分。 如果需要,请随时在另一个StackOverflow问题中寻求帮助。

scala> def rawPythagTriples =
   for { c <- Iterator from 1; a <- 1 until c; b <- a until c if a*a + b*b == c*c }
     yield (a,b,c)
rawPythagTriples: Iterator[(Int, Int, Int)]
scala> (rawPythagTriples take 10).toList
res2: List[(Int, Int, Int)] = List((3,4,5), (6,8,10), (5,12,13), (9,12,15), (8,15,17), (12,16,20), (7,24,25), (15,20,25), (10,24,26), (20,21,29))

请注意,我们从斜边开始,从而约束ab。 顺便说一下,您可以进行一些小的优化,例如从 5 开始c,从 2 开始a,在 a+1 开始b

在 REPL 中有效:

def foo = {
  val s = Stream.from(1)
  s.flatMap(x =>
    s.flatMap(y =>
      s.flatMap(z => List(x,y,z))))
}
scala> foo.take(15) mkString ", "
res24: String = 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1, 4, 1, 1, 5

您的 f(x,y,z) 必须返回一个扩展 GenTraversableOnce[?] 子类的类型。

最新更新