Scala:整个流的过滤器强制求值

Scala:整个流的过滤器强制求值,scala,filter,stream,Scala,Filter,Stream,下面的代码从类的构造函数中调用一次的方法本身调用一次。当它作为specs UnitTest的一部分执行时,测试就会被卡住,一个javaw进程会迅速消耗更多的内存 private def placeMines( excludes: List[( Int, Int )] ) { def rndstream: Stream[( Int, Int )] = { def s: Stream[( Int, Int )] = ( Random.nextInt(

下面的代码从类的构造函数中调用一次的方法本身调用一次。当它作为specs 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=>true。有趣的是,它在真实情况下终止,但在错误情况下永远运行。插入一些println表明,在我终止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 stream filter无尽”、“scala stream filter强制求值”和“scala stream filter不终止”时,只会出现一些教程,展示流的用法,这些教程在原则上似乎与我的代码相同

我想你的过滤功能有问题
Stream.filter
尝试查找第一个匹配值,如果没有匹配值,它将永远搜索

以流和调用为例

s.filter(_ => false)

这将不会返回,因此它必须是您的筛选函数。

我再次检查,虽然谓词负责这些症状,但原因在于testcase、ysize和xsize。具体来说,我有一组使用1*1网格的测试用例,在这种情况下,Random.next(*size)显然总是返回0。但由于我也有(0,0)::Nil被指定为排除谓词的第一部分,因此其计算结果总是为false。我想我会做出改变,要求ysize*xsize至少为2。我感谢您花时间回答我的问题,并为浪费您的时间表示歉意,因为我本应该从一开始就对我的谓词提出更多问题。顺便说一下,可以简化
rndstream
方法:
def rndstream:Stream[(Int,Int)]=(Random.nextInt(ysize),Random.nextInt(xsize));::rndstream