私は Scala に非常に慣れていないので、私の無知を許してください! 最大値に制限された整数のペアを反復しようとしています。たとえば、最大値が 5 の場合、反復は次のように返されます。
(0, 0), (0, 1), ..., (0, 5), (1, 0), ..., (5, 5)
これをストリームとして末尾再帰的に返すことにしました。
@tailrec
def _pairs(i: Int, j: Int, maximum: Int): Stream[(Int, Int)] = {
if (i == maximum && j == maximum) Stream.empty
else if (j == maximum) (i, j) #:: _pairs(i + 1, 0, maximum)
else (i, j) #:: _pairs(i, j + 1, maximum)
}
tailrec 注釈がないと、コードは機能します。
scala> _pairs(0, 0, 5).take(11)
res16: scala.collection.immutable.Stream[(Int, Int)] = Stream((0,0), ?)
scala> _pairs(0, 0, 5).take(11).toList
res17: List[(Int, Int)] = List((0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (1,0), (1,1), (1,2), (1,3), (1,4))
しかし、これは私には十分ではありません。コンパイラは、_pairs の最後の行が _pairs を返していないことを正しく指摘しています。
could not optimize @tailrec annotated method _pairs: it contains a recursive call not in tail position
else (i, j) #:: _pairs(i, j + 1, maximum)
^
だから、私はいくつかの質問があります:
- 上記の実装に直接対処すると、どのように末尾再帰的に Stream[(Int, Int)] を返すのでしょうか?
- 一歩下がって、整数の制限されたシーケンスを反復処理する最もメモリ効率の良い方法は何ですか? Range は IndexedSeq を拡張するため、Range を反復処理したくありません。また、シーケンス全体をメモリ内に存在させたくありません。それとも私が間違っていますか?Range.view を繰り返し処理すると、それがメモリに入らないようにできますか?
Python (!) では、私が欲しいのは次のとおりです。
In [6]: def _pairs(maximum):
...: for i in xrange(maximum+1):
...: for j in xrange(maximum+1):
...: yield (i, j)
...:
In [7]: p = _pairs(5)
In [8]: [p.next() for i in xrange(11)]
Out[8]:
[(0, 0),
(0, 1),
(0, 2),
(0, 3),
(0, 4),
(0, 5),
(1, 0),
(1, 1),
(1, 2),
(1, 3),
(1, 4)]
ご協力いただきありがとうございます!参考文献や API ドキュメントなどを読む必要があると思われる場合は、教えてください。私は学びたいと思っているからです。