4

次のコードは、クラスのコンストラクター内で1回呼び出されるメソッド自体から1回呼び出されます。スペック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() )
}

何が起こっているのかを知るために、最後の行を副作用(グリッドは2次元配列)でコメントアウトし、フィルター述語を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 )
    }
}

ただし、そのコードは問題なく実行されます。

「scalastreamfilterendless」、「scala streamfilterforcesvaluation」および「scalastreamfilterdoes not end」の検索では、原則として私のコードと同じように見えるストリームの使用法を示すチュートリアルのみが表示されました。

4

1 に答える 1

3

フィルター機能に問題があると思います。Stream.filter最初に一致する値を見つけようとし、何もない場合は永遠に検索します。

サンプル ストリームを取得して呼び出します

s.filter(_ => false)

これは返されないため、フィルター関数にする必要があります。

于 2013-01-10T15:17:21.727 に答える