Scala:过滤器强制评估整个流

标签 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 => true。有趣的是,它在 true 情况下终止,但一直以 false 运行。插入一些 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 流过滤器不会终止”只提供了展示流用法的教程,这些教程在原则上与我的代码相同。

最佳答案

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

以您的示例流并调用

s.filter(_ => false)

这不会返回,因此它必须是您的过滤器功能。

关于Scala:过滤器强制评估整个流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14259516/

相关文章:

scala - 这两个高阶函数有何不同?

javascript - 为什么这个 array.filter 总是什么都不返回?

c# - 如何解析多部分 HttpWebResponse

javascript - 搜索过滤器不起作用。 Angular Js

javascript - 使用 highland.js 执行一系列异步任务并引用原始流数据

c# - 为什么c#内置的IO类比自制的快?

scala - 将数据框列转换为元组列表

scala - ( Play 2.4)特征中的依赖注入(inject)?

scala - Gatling - 没有定义名为 'CSRF' 的属性

c# - 在 .Net 中过滤 DataGridView 行