开发者

How am I *supposed* to use a scala.collection.immutable.Queue?

I have what I would think is the most common case for processing a queue. I will read off the front of the queue, act on the element (which may cause more elements to be 开发者_Python百科added to the queue), and then loop until the queue is empty.

  1. My first instinct was foreach, but no, apparently a queue (even a mutable one) is strict and the foreach loops over all the elements that are in the queue when the iteration starts.
  2. I cannot figure out the syntax for a while loop.

You'd think that it would be something like

while (!q.isEmpty) {
   var (e, q) = q.dequeue
   ... }

would work, except that I'm redeclaring q. This does work:

while (!q.isEmpty) {
   var (e, q1) = q.dequeue
   q = q1
   ... }

but man, does it look wrong ...


Here's one way to avoid any vars at all:

val q0 = collection.immutable.Queue("1","Two","iii")
Iterator.iterate(q0) { qi =>
  val (e,q) = qi.dequeue
  println("I just dequeued "+e)  // Your side-effecting operations go here
  if (e.length!=2) q.enqueue("..")  // Your changes to the queue go here
  else q
}.takeWhile(! _.isEmpty).foreach(identity)

You start with the initial queue, q0, and then on the qith step, you dequeue something and produce a new queue if need be, returning that for the next step.

All you have left is the stopping condition (not empty), and then since this just defines a process, not the actual action, you have to run it (using a no-op foreach, for example).


While Rex Kerr's answer is good, iterators are mutable. Here's a truly immutable solution, modeled very closely on the code in Rex Kerr's own answer.

val q0 = collection.immutable.Queue("1","Two","iii")
@annotation.tailrec def processQueue(queue: collection.immutable.Queue[String]): Unit = if (queue.nonEmpty) {
    val (element, rest) = queue.dequeue
    println("I just dequeued "+element)
    if (element.length != 2) processQueue(rest.enqueue(".."))
    else processQueue(rest)
}
processQueue(q0)


Processing a Queue in a while loop can be done without a duplicate var/val as follows:

var q = Queue("foo", "bar", "baz")
while (q.nonEmpty) {
  val e = q.head
  q = q.tail
  // Do something with `e` here
}

(I am aware that this answer is 7 years late, but I thought it a valuable alternative nonetheless.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜