I'm writing a simulation where a number of operators take work from a single queue. At each time step I need to sequentially check elements of a sequence, and if a condition passes replace the current value with an item from the queue. What remains in the queue must be retained for later iterations.
I've written a routine called patch to do this, but it doesn't seem very neat. Is there a more idiomatic way to achieve the same thing? I'd like it to be fairly fast but still functional in style.
import scala.annotation.tailrec
import scala.collection.immutable.Queue
object SeqPimp extends App{
val mySeq = Seq('a', 'B', 'C', 'd', 'E')
val shortQ = Queue('+','-')
val longQ = Queue('+','-','*','/','%')
println(patch(mySeq)(_.isUpper, shortQ))
//Output: (List(a, +, -, d, E),Queue())
println(patch(mySeq)(_.isUpper, longQ))
//Output: (List(a, +, -, d, *),Queue(/, %))
def patch[T](to: Seq[T])(condition: T => Boolean, from: Queue[T]): (Seq[T], Queue[T]) = {
@tailrec
def go(acc: Seq[T], remaining: Seq[T], q: Queue[T]): (Seq[T], Queue[T]) = {
if(acc.size == to.size) (acc.reverse, q)
else if(q.size == 0) (acc.reverse ++: remaining, q)
else{
if(condition(remaining.head)){
val (item, q1) = q.dequeue
go(item +: acc, remaining.tail, q1)
}else{
go(remaining.head +: acc, remaining.tail, q)
}
}
}
go(Nil, to, from)
}
}