2010-12-27 5 views
22

대기열을 처리하는 가장 일반적인 경우라고 생각합니다. 큐의 앞부분을 읽은 다음 엘리먼트에 작용하여 (큐에 더 많은 엘리먼트가 추가 될 수 있음) 대기열이 비워 질 때까지 반복한다.scala.collection.immutable.Queue를 어떻게 사용합니까?

  1. 나의 첫번째 본능 foreach했지만, 아니, 분명히 큐 (심지어 변경 가능한 한) 엄격하고 foreach는 큐 반복 시작에있는 모든 요소를 ​​반복합니다.
  2. while 루프 구문을 이해할 수 없습니다.

당신은 내가 q를 재 선언하고있어 것을 제외하고, 일하는 것이

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

같은 것을 할 것이라고 생각할 것입니다. 이 작업을 수행합니다

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

하지만 사람이이 잘못를 ... 보는가

+2

괜찮아 보이는 군. –

답변

17

여기에 전혀 바르를 방지하는 방법 중 하나입니다 : 당신은 초기 큐 시작

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 번째 단계에서, 필요하다면 무언가를 축출하고 새로운 대기열을 생성하고, 다음 단계를 위해 대기열을 반환합니다.

남은 것은 중지 조건 (비어 있지 않음)이며, 실제 작업이 아닌 프로세스를 정의하기 때문에 실행해야합니다 (예 : no-op foreach 사용).

+0

이제 * 좋은거야. 나는 그것을 시도하지 않았지만 그것이 내가 염두에 두었던 것이다. 실제로 대기열에 대한 추가 작업은 부작용 작업의 호출 트리에서 수행되고 있으므로 일시적인 대기 영역을 사용할 수있게해야 할 수도 있지만 작동한다고 생각합니다. – Malvolio

13

Rex Kerranswer은 좋지만 이터레이터는 변경할 수 있습니다. 여기 Rex Kerr의 답변에 나온 코드를 기반으로 매우 불변의 해결책이 있습니다.

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 사용하는 모든 실제 프로세서가 수행 할 수 없기 때문에 모든 코드가 내부적으로 변경 가능합니다 변이가없는 한가지, 그래서 논쟁은 절대적으로 곤란합니다. 프로그래머와 관련이없는 컴파일러 측 최적화입니다. –

+6

이 질문과 다양한 답변에서 아무것도 얻지 못한다면 그것은 "그 논증은 절대적으로 야단법석입니다"라는 표현인데, 나는 바로 그 다음 기회에 자주 사용하려고합니다. – Malvolio

4

while 루프에서 Queue 다음과 같이 중복 var/val없이 할 수 처리 :

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

(나는이 대답은 칠년 말 것을 알고,하지만 난 그래도 가치있는 대안이라고 생각했습니다.)

관련 문제