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.
- 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. - 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 qi
th 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.)
精彩评论