Tôi đã xem xét câu hỏi này nhưng vẫn không hiểu sự khác biệt giữa các đặc điểm Có thể duyệt và Có thể duyệt. Ai đó có thể giải thích?
Tôi đã xem xét câu hỏi này nhưng vẫn không hiểu sự khác biệt giữa các đặc điểm Có thể duyệt và Có thể duyệt. Ai đó có thể giải thích?
Câu trả lời:
Nói một cách đơn giản, các trình vòng lặp giữ trạng thái, các trình duyệt thì không.
Một Traversablecó một phương pháp trừu tượng: foreach. Khi bạn gọi foreach, bộ sưu tập sẽ cung cấp cho hàm đã truyền tất cả các phần tử mà nó giữ, cái này đến phần tử khác.
Mặt khác, một Iterablephương thức có as trừu tượng iterator, trả về một Iterator. Bạn có thể gọi nextmột Iteratorđể nhận phần tử tiếp theo tại thời điểm bạn chọn. Cho đến khi bạn làm vậy, nó phải theo dõi vị trí của nó trong bộ sưu tập và những gì tiếp theo.
Iterablemở rộng Traversable, vì vậy tôi đoán bạn có nghĩa là Traversables mà không phải Iterablelà s.
Traversablegiao diện không yêu cầu giữ trạng thái, trong khi tuân thủ Iteratorgiao diện thì có.
Traversables Iterablekhông giữ bất kỳ trạng thái lặp lại nào. Nó Iteratorđược tạo và trả lại bởi Iterablecái giữ trạng thái.
Hãy coi đó là sự khác biệt giữa thổi và hút.
Khi bạn gọi một Traversables foreachhoặc các phương thức dẫn xuất của nó, nó sẽ thổi các giá trị của nó vào hàm của bạn tại một thời điểm - vì vậy nó có quyền kiểm soát việc lặp lại.
Với giá trị Iteratortrả về bởi một Iterablemặc dù, bạn hút các giá trị ra khỏi nó, tự mình kiểm soát thời điểm chuyển sang giá trị tiếp theo.
tl; dr Iterables là những Traversablesthứ có thể tạo ra trạng tháiIterators
Đầu tiên, hãy biết rằng đó Iterablelà trang con của Traversable.
Thứ hai,
Traversableyêu cầu triển khai foreachphương thức, được sử dụng bởi mọi thứ khác.
Iterableyêu cầu triển khai iteratorphương thức, được sử dụng bởi mọi thứ khác.
Ví dụ, việc findáp Traversabledụng cho các sử dụng foreach(thông qua một để hiểu) và ném một BreakControlngoại lệ để dừng lặp lại khi đã tìm thấy phần tử thỏa mãn.
trait TravserableLike {
def find(p: A => Boolean): Option[A] = {
var result: Option[A] = None
breakable {
for (x <- this)
if (p(x)) { result = Some(x); break }
}
result
}
}
Ngược lại, hàm Iterabletrừ sẽ ghi đè triển khai này và gọi findhàm Iterator, chỉ đơn giản là dừng lặp lại khi phần tử được tìm thấy:
trait Iterable {
override /*TraversableLike*/ def find(p: A => Boolean): Option[A] =
iterator.find(p)
}
trait Iterator {
def find(p: A => Boolean): Option[A] = {
var res: Option[A] = None
while (res.isEmpty && hasNext) {
val e = next()
if (p(e)) res = Some(e)
}
res
}
}
Sẽ rất tốt nếu bạn không ném ra các ngoại lệ để Traversablelặp lại, nhưng đó là cách duy nhất để lặp lại một phần khi chỉ sử dụng foreach.
Từ một góc độ, Iterablelà đặc điểm đòi hỏi cao hơn / mạnh mẽ hơn, vì bạn có thể dễ dàng triển khai foreachbằng cách sử dụng iterator, nhưng bạn không thể thực sự triển khai iteratorbằng cách sử dụng foreach.
Tóm lại, Iterablecung cấp một cách để tạm dừng, tiếp tục hoặc ngừng lặp lại thông qua trạng thái Iterator. Với Traversable, tất cả hoặc không có gì (không có ngoại lệ cho điều khiển luồng).
Hầu hết thời gian điều đó không quan trọng và bạn sẽ muốn có giao diện chung hơn. Nhưng nếu bạn cần kiểm soát tùy chỉnh nhiều hơn đối với việc lặp lại, bạn sẽ cần một Iterator, mà bạn có thể truy xuất từ một Iterable.
Câu trả lời của Daniel nghe hay đấy. Hãy để tôi xem nếu tôi có thể diễn đạt nó theo cách của riêng tôi.
Vì vậy, một Iterable có thể cung cấp cho bạn một trình vòng lặp, cho phép bạn duyệt qua các phần tử một cách lần lượt (sử dụng next ()) và dừng lại và đi tùy ý. Để làm điều đó, trình lặp cần giữ một "con trỏ" nội bộ đến vị trí của phần tử. Nhưng một Traversable cung cấp cho bạn phương pháp, foreach, để duyệt qua tất cả các phần tử cùng một lúc mà không dừng lại.
Một cái gì đó như Phạm vi (1, 10) chỉ cần có 2 số nguyên ở trạng thái có thể chuyển ngang. Nhưng Phạm vi (1, 10) như một Lặp lại cung cấp cho bạn một trình vòng lặp cần sử dụng 3 số nguyên cho trạng thái, một trong số đó là chỉ mục.
Xem xét rằng Traversable cũng cung cấp foldLeft, foldRight, bước trước của nó cần phải duyệt các phần tử theo một thứ tự đã biết và cố định. Do đó, có thể triển khai một trình vòng lặp cho một Trình duyệt. Ví dụ: def iterator = toList.iterator
Traversabletrong Scala 2.13 (nó vẫn được giữ như một bí danh NỮA choIterableđến 2.14)