2013-05-03 23 views
6

Tôi đang chạy các đoạn mã sau:Scala - lặp và takeWhile

val it = List(1,1,1,2,2,3,3).iterator.buffered 
val compare = it.head 
it.takeWhile(_ == compare).toList 

và nó sẽ trả về (1,1,1). Tuy nhiên, nếu tôi chạy như sau:

val it = List(1,1,1,2,2,3,3).iterator.buffered 
it.takeWhile(_ == it.head).toList 

Tôi nhận được (1,1). Tại sao điều này là trường hợp? Không phải là head được đánh giá khi gọi takeWhile và kết quả sẽ giống nhau không?

Trả lời

15

Do trình vòng lặp có thể thay đổi, giá trị của it.head phụ thuộc vào thời điểm được đánh giá.

Kiểm tra implementation of takeWhile cho thấy rằng nó loại bỏ phần đầu của trình lặp số trước khi áp dụng biến vị ngữ.

Vì vậy, trong lần lặp thứ ba, it.head được đánh giá từ bên trong vị từ sẽ là 2, bởi vì phần tử thứ ba đã bị xóa.

Đây là minh họa về lý do bạn nên chọn bất biến. Nó quy định một lớp toàn bộ hành vi không rõ ràng như thế này.

0

Thêm vào @Ben James trả lời ở trên. Dưới đây là takeWhile phương pháp mã (credits: ben):

def hasNext = hdDefined || tail.hasNext && { 
    hd = tail.next() //line 2 
    if (p(hd)) hdDefined = true 
    else tail = Iterator.empty 
    hdDefined 
} 

Trong lần lặp thứ ba sau dòng 2, giá trị là: hd=1 và còn lại Iterator là List(2,2,3,3). khi gọi số p(hd), nó sẽ kiểm tra số head của vòng lặp trong trường hợp này là 2. Do đó nó phá vỡ.

Các vấn đề liên quan