11

次の状況で

trait T {

 @tailrec
 def consume[A](as: Stream[A]): Unit = {
    if (as.isEmpty) ()
    else consume(as.tail)
  }
 }

object O extends T

十分な大きさで呼び出すO.consume(Range(1, N).toStream)N、プログラムはメモリを使い果たすか、少なくとも必要なO(1)ではなくO(N)を消費します。

4

2 に答える 2

12

特性に対して末尾再帰メソッドが生成されます。トレイトのエクステンダー(ここO)のメソッドエントリは、呼び出しをトレイトのメソッドに転送しますが、そうしている間、ストリームのヘッドへの参照を保持します。

したがって、このメソッドは末尾再帰ですが、メモリを解放することはできません。対処法:ストリーム関数を特性で定義しないでください。オブジェクトで直接定義してください。

別の方法はscalazですEphemeralStream。これは、ストリームのヘッドとテールへの弱参照を保持し、必要に応じてそれらを再計算します。

于 2012-09-18T23:57:41.800 に答える