2011-11-06 23 views
8

Tôi đang đọc "Lập trình trong Scala 2". Trong phần 24.4, nó lưu ý rằng Iterable chứa nhiều phương thức mà không thể được viết một cách hiệu quả mà không có một trình lặp. Bảng 24.2 chứa các phương pháp này. Tuy nhiên, tôi không hiểu tại sao một số người trong số họ không thể được thực hiện hiệu quả trên iterator. Ví dụ, hãy xem xét zipWithIndex.Tại sao zipWithIndex được triển khai trong Iterable và không Traversable?

def zipWithIndex[A1 >: A, That](implicit bf: CanBuildFrom[Repr, (A1, Int), That]): That = { 
    val b = bf(repr) 
    var i = 0 
    for (x <- this) { 
     b += ((x, i)) 
     i +=1 
    } 
    b.result 
    } 

Tại sao không di chuyển định nghĩa này sang đi ngang? Dường như với tôi rằng mã có thể giống hệt nhau và sẽ không có sự khác biệt về hiệu quả.

+0

Chỉ muốn thêm một trường hợp sử dụng cho 'zipWithIndex' trên 'traversable '. Điều gì sẽ xảy ra nếu bạn đang thực hiện một phương thức để chọn một phần tử ngẫu nhiên từ một mạng di chuyển? Khi lặp qua các phần tử, bạn cần một chỉ mục để trợ giúp với các xác suất, mặc dù chỉ mục không tương ứng với một vị trí bền vững với cấu trúc. – schmmd

Trả lời

11

Bạn hoàn toàn chính xác và việc triển khai của bạn sẽ hoạt động. Không có lý do chính đáng để có zipWithIndex được xác định trong Iterable và không phải Traversable; không đảm bảo bất kỳ sự bảo đảm nào về thứ tự của các phần tử trong quá trình truyền tải.

(Đây là câu trả lời đầu tiên của tôi trên StackOverflow. Hy vọng tôi đã giúp đỡ. :) Nếu tôi đã không, xin vui lòng cho tôi biết.)

+0

Hoàn toàn hữu ích, bạn có +6 cho điều đó! Tôi đã chỉ đảm bảo rằng tôi không thiếu một cái gì đó như chương rõ ràng nói rằng các phương pháp trong bảng được thực hiện trong Iterable bởi vì chúng được dễ dàng hơn hoặc hiệu quả hơn ở đó. – schmmd

10

Traversable không đảm bảo trật tự trong đó các phần tử sẽ được viếng thăm và chỉ đòi hỏi bạn phải xác định một phương pháp foreach với chữ ký sau đây:

def foreach[U](f: Elem => U): Unit 

Vì phương pháp này chỉ cần gọi f cho mỗi phần tử trong bất kỳ thứ tự nào, không có ý nghĩa để có chỉ mục về các yếu tố vì thứ tự có thể khác nhau đối với mỗi lệnh gọi foreach.

Chỉnh sửa: Đây thực sự chỉ là một lời giải thích, tại sao nó không có trên Traversable. Như Luigi đã chỉ ra trong các ý kiến, zipWithIndex sẽ có ý nghĩa hơn trên Seq.

+1

Tôi đồng ý rằng các chỉ mục không có nghĩa là trên một 'Traversable' (xem xét các đồ thị ví dụ). Đặc biệt, bạn sẽ không thể làm bất cứ điều gì với chỉ mục thu được * trên bộ sưu tập *. Nhưng bạn có thể muốn có chỉ số "vòng lặp" cho một cái gì đó khác (và chỉ là bắt chước có 'i' trong một vòng lặp' for' kiểu Java điển hình), vậy tại sao không? – Raphael

+1

'Iterable' (bao gồm các bản đồ và tập hợp) không đảm bảo thứ tự trong đó các thành phần sẽ được truy cập. Một câu hỏi hay hơn sẽ hỏi tại sao 'zipWithIndex' được định nghĩa trên' Iterable' thay vì 'Seq'. –

+0

Sau cuộc thảo luận này, có vẻ như foreach có ý nghĩa hơn đối với Traversable (tại sao không) hoặc Seq (thứ tự guarenteed)! – schmmd

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