下面的代码从类的构造函数中调用一次的方法本身调用一次。当它作为规范 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 情况下一直运行。在我终止 java 进程之前,插入一些 println 显示谓词被调用了数十万次。
我尝试使用以下代码重现这种情况:
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 流过滤器不终止”只提出了教程,展示了流的用法,这在原则上与我的代码相同。