I have a recursive function that I'm trying to do @tailrec if the inner, recursive part ( countR3 ) adds items to the queue ( agenda is scala.collections.mutable.Queue ). My idea is then to move the outer part of the function above the agenda and summarize the results.
NOTE. This was a home issue, so I do not want to publish all the code; however, implementing tail recursion was not part of the homework.
Here is the piece of code related to my question:
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
It almost seems to work ... The problem is that it does not iterate over all the items added to the agenda, but it does handle some of them. You can see it in the following figure:
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))
[Of the six items on the final agenda, only the first three were processed.]
I am generally well aware of the dangers of a collection mutation as long as you repeat it, say, in Java. But the line is a kind of horse of a different color. Of course, I understand that I can just write an imperative loop, for example:
var count = 0 while (!agenda.isEmpty) { val pair = agenda.dequeue() count += countR3(pair._1, pair._2) }
This works fine, but this is Scala, I am investigating if there is a more functionally elegant way.
Any suggestions?