Scala:过滤强制评估整个Stream

时间:2013-01-10 13:52:56

标签: scala filter stream

以下代码从类的构造函数中调用一次的方法本身调用一次。当它作为规范UnitTest的一部分执行时,测试卡住了,并且生成了一个快速消耗更多内存的javaw进程。

private def placeMines( excludes: List[( Int, Int )] ) {
    def rndstream: Stream[( Int, Int )] = {
        def s: Stream[( Int, Int )] =
            ( Random.nextInt( ysize ), Random.nextInt(  xsize ) ) #:: s
        s
    }
    def posPermitted( pos: ( Int, Int ) ): Boolean = {
        !excludes.contains( pos ) &&
            fieldEmpty( pos._1, pos._2 )
    }
    val positions = rndstream.filter( posPermitted )
    positions.take( minecount ).foreach( x => grid( x._1 )( x._2 ) = MineField() )
}

为了找出发生了什么,我已经注释了具有副作用的最后一行(网格是二维数组)并用不同的替换了过滤谓词,包括x => false和x =>真正。有趣的是,它终结于真实的情况下,但始终以虚假的方式运行。插入一些printlns表明,在终止java进程之前,谓词被调用了数十万次。

我尝试使用以下代码重现这种情况:

import scala.util.Random
import org.specs.SpecificationWithJUnit

class foobar extends SpecificationWithJUnit {
    val x = 0xDead
    val y = 0xBeef

    bar(x, y)

    private def bar(x: Int, y: Int) = foo(x)

    private def foo(x: Int) = {
        def s: Stream[( Int, Int )] = {
            def p: Stream[( Int, Int )] =
                ( Random.nextInt( x ), Random.nextInt( y ) ) #:: p
            p
        }
        val fiveodd = s.filter( x => x._1 % 2 == 1 )
        println( fiveodd.take( 5 ).toList )
    }
}

然而,该代码运行得很好。

搜索“scala流过滤器无尽”“scala流过滤器强制评估”和“scala流过滤器不终止”只提出了教程,展示了原则上与我的代码相同的流的用法。

1 个答案:

答案 0 :(得分:3)

我猜您的过滤功能有问题。 Stream.filter尝试查找第一个匹配值,如果没有,则会永久搜索。

获取示例流并致电

s.filter(_ => false)

这不会返回,所以它必须是你的过滤功能。