7

@tailrec内部の再帰部分 ( countR3) に要素をキュー ( agendais a ) に追加させることで作成しようとしている再帰関数がありますscala.collections.mutable.Queue。私の考えは、関数の外側の部分を議題の上に折り畳み、結果を合計することです。

注: これ宿題だったので、コード全体を投稿したくありません。ただし、実装を末尾再帰にすることは宿題の一部ではありませんでした。

私の質問に関連するコードの部分は次のとおりです。

import scala.collection.mutable.Queue

val agenda: Queue[Tuple2[Int, List[Int]]] = Queue()

@tailrec
def countR3(y: Int, x: List[Int]): Int = {
  if (y == 0) 1
  else if (x.isEmpty) 0
  else if …
  else {
    agenda.enqueue((y - x.head, x))
    countR3(y, x.tail)
  }
}
⋮
agenda.enqueue((4, List(1, 2)))
val count = agenda.foldLeft(0) {
  (count, pair) => {
    val mohr = countR3(pair._1, pair._2)
    println("count=" + count + " countR3=" + mohr)
    count + mohr
  }
}
println(agenda.mkString(" + "))
count

これはほとんど機能しているように見えます...問題は、議題に追加されたすべてのアイテムを反復処理するわけではなく、それらの一部を処理することです。これは、以下の出力で確認できます。

count=0 countR3=0
count=0 countR3=0
count=0 countR3=0
(4,List(1, 2)) + (3,List(1, 2)) + (2,List(2)) + (2,List(1, 2)) + (1,List(2)) + (0,List(2))

[最終議題の 6 つの項目のうち、最初の 3 つだけが処理されました。]

私は一般的に、たとえば Java でコレクションを繰り返し処理しているときにコレクションを変更することの危険性を十分に認識しています。しかし、キューは一種の別の色の馬です。もちろん、次のように命令型ループを単純に記述できることは理解しています。

var count = 0
while (!agenda.isEmpty) {
  val pair = agenda.dequeue()
  count += countR3(pair._1, pair._2)
}

これは完全にうまく機能しますが、これは Scala であるため、より機能的にエレガントな方法があるかどうかを調べています。

助言がありますか?

4

1 に答える 1