2010-12-27 14 views
22

Bir kuyruğu işlemek için en yaygın olanı düşünürüm. Kuyruğun ön kısmını okuyacağım, eleman üzerinde hareket edeceğim (sıraya eklenecek daha fazla öğeye neden olabilir) ve sıra boşalana kadar döngü geçireceğim.Bir scala.collection.immutable.Queue kullanmak nasıl * * * * *

  1. Benim ilk içgüdüsü foreach, ama hayır, görünüşe bir kuyruk (hatta bir değişken bir) katı ve foreach kuyrukta yineleme başlar bulunan tüm unsurları üzerinde döngüler.
  2. while döngüsünün sözdizimini anlayamıyorum.

Bunu ben q redeclaring ediyorum dışında çalışacak

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

gibi bir şey olacağını düşünmek istiyorum. Bu nasıl çalışır:

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

ama adam, o yanlış ... görünüyor

+2

Yanlış görünüyor ama sorun değil. –

cevap

17

Burada hiç bir değişkenler önlemek için tek yoldur: İlk kuyrukta ile başlar

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, ve daha sonra qi th adımında, bir şey dequeue ve gerekirse bir sonraki adım için döndürerek, yeni bir sıra üretmek.

Tek bıraktığınız durma koşulu (boş değil), ve bu sadece bir işlemi tanımladığından, gerçek eylemi değil, onu çalıştırmanız gerekir (örneğin, no-op foreach kullanarak).

+0

Şimdi * bu * iyi. Denemedim ama aklımda olan şey buydu. Aslında, kuyruğa yapılan eklemeler, yan etki operasyonlarının çağrı ağacında derin bir şekilde yapılmakta, bu yüzden geçici bir elverişli alan bulundurmak zorunda kalabilirim, ama bunun işe yarayacağını düşünüyorum. – Malvolio

13

Rex Kerr ürününün answer iyi olmasına rağmen yineleyiciler değiştirilebilir. İşte Rex Kerr'in kendi cevabının koduna çok benzeyen gerçekten değişmez bir çözüm.

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

Kuyruk özyinelemeli kod dahili olarak; Sadece ondan korunmuşsun. Yaptığım gibi kullanılan yineleyici modelinin de sizi değişken içsellerden koruduğu göz önüne alındığında, bu durumda ayrımı görmüyorum. (Yine de kuyruk özlemini nasıl kullanacağımı bilmek değerli olduğunu düşünürsek, bu tür problemler için genellikle daha garip bir sözdizimine sahiptir.) –

+1

@Rex Kerr Kullandığımız tüm gerçek işlemciler, her kod dahili olarak değiştirilemez. mutabilite olmaksızın tek bir şey, bu yüzden argüman kesinlikle bollocks. Programlayıcıyı ilgilendirmeyen bir derleyici tarafı optimizasyonu. –

+6

Bu sorudan ve çeşitli cevaplardan başka bir şey elde edemezsem, bir sonraki fırsatta ve daha sonra sık sık kullanmayı planladığım "bu argüman kesinlikle bollocks" ifadesidir. – Malvolio

4

bir while döngü içinde bir Queue şöyle tekrarlayanı var/val olmadan yapılabilir işleme:

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

(Bu cevap 7 yıl geç olduğunun farkındayım, ama ben yine de değerli bir alternatif olduğunu düşündüm.)

İlgili konular