2010-12-27 2 views
22

私はキューを処理する最も一般的なケースだと思います。私はキューの先頭から読み込み、要素に作用して(要素にキューを追加する可能性があります)、キューが空になるまでループします。scala.collection.immutable.Queueを使用する方法は?

  1. 私の最初の本能はforeachだったが、いや、どうやらキュー(でも変更可能なもの)が厳密で、foreachのは、反復開始キューにあるすべての要素をループします。
  2. whileループの構文を理解できません。あなたはそれが

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

    ようなものになるだろうと思うだろう

は私がqを再宣言だことを除いて、働くだろう。これは、作業を行います。

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

しかし男性は、それが間違っを...見てない

+2

それは間違っているようだが大丈夫だ。 –

答えて

17

ここではまったくVARSを回避するための一つの方法です:あなたが最初のキューで始まる

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) 

は、 、q0、そしてqi番目のステップでは、何かをデキューして、必要に応じて新しいキューを生成し、次のステップのためにそれを返します。

あなたが残したのは、停止条件(空ではない)だけで、実際のアクションではなくプロセスを定義するだけなので、実行する必要があります(たとえば、foreachを使用しない)。

+0

今は*良いです。私はそれを試していないが、それは私が心に持っていたものです。実際には、副作用操作の呼び出しツリーではキューへの追加が深く行われているため、一時的な保持領域を使用可能にする必要があるかもしれませんが、機能すると思います。 – Malvolio

13

Rex Kerranswerは良いですが、イテレータは変更可能です。 Rex Kerr自身の答えのコードを非常によく模倣した、真に不変な解決法があります。

次のように whileループで Queueを処理
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) 
+0

テール再帰コードは内部的に変更可能です。あなたはただそれから保護されています。私が使ったイテレーター・パターンは、内部の変化からあなたを守りますので、私はこの場合の区別は見られません。 (末尾の再帰を使う方法を知っていることは価値があると思うが、この種の問題に対しては、より扱いにくい構文になっていることが多い)。 –

+1

@Rex Kerrすべてのコードは内部で変更可能である。 mutabilityのない単なるものなので、議論は絶対に禁欲的です。これはプログラマに関係のないコンパイラ側の最適化です。 –

+6

私はこの質問とさまざまな反応から何も得られない場合、それは「その議論は絶対に騒動です」という表現です。私は次の機会に頻繁に使用するつもりです。 – Malvolio

4

var/val重複せずに行うことができます。

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

(私はこの答えは7年遅れていることを承知していますが、私それにもかかわらず、貴重な代替案だと思った。)

関連する問題