Saya telah melihat pertanyaan ini tetapi masih tidak memahami perbedaan antara sifat Iterable dan Traversable. Bisakah seseorang menjelaskan?
Saya telah melihat pertanyaan ini tetapi masih tidak memahami perbedaan antara sifat Iterable dan Traversable. Bisakah seseorang menjelaskan?
Jawaban:
Sederhananya, iterator mempertahankan status, tidak dapat dilintasi.
Sebuah Traversable
memiliki satu metode abstrak: foreach
. Saat Anda memanggil foreach
, collection akan memberi makan fungsi yang diteruskan semua elemen yang disimpannya, satu demi satu.
Di sisi lain, metode Iterable
has as abstrak iterator
, yang mengembalikan Iterator
. Anda dapat memanggil next
pada Iterator
untuk mendapatkan elemen berikutnya pada waktu yang Anda pilih. Sampai Anda melakukannya, itu harus melacak di mana itu dalam koleksi, dan apa selanjutnya.
Iterable
meluas Traversable
, jadi saya rasa maksud Anda Traversable
s yang bukan Iterable
s.
Traversable
antarmuka tidak memerlukan status penyimpanan, sementara mematuhi Iterator
antarmuka memerlukannya .
Traversable
s yang Iterable
tidak menyimpan status iterasi apa pun. Itu Iterator
dibuat dan dikembalikan oleh Iterable
yang menjaga negara.
Anggap saja sebagai perbedaan antara meniup dan menghisap.
Ketika Anda memiliki panggilan Traversable
s foreach
, atau metode turunannya, itu akan meledakkan nilainya ke dalam fungsi Anda satu per satu - sehingga ia memiliki kendali atas iterasi.
Dengan pengembalian Iterator
oleh Iterable
meskipun, Anda menyedot nilai darinya, mengontrol kapan harus pindah ke yang berikutnya sendiri.
tl; dr Iterables
adalah Traversables
yang dapat menghasilkan statefulIterators
Pertama, ketahuilah bahwa itu Iterable
adalah inti dari Traversable
.
Kedua,
Traversable
membutuhkan penerapan foreach
metode, yang digunakan oleh yang lainnya.
Iterable
membutuhkan penerapan iterator
metode, yang digunakan oleh yang lainnya.
Misalnya, implementasi find
for Traversable
use foreach
(melalui pemahaman for) dan melontarkan BreakControl
pengecualian untuk menghentikan iterasi setelah elemen yang memuaskan ditemukan.
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
}
}
Sebaliknya, Iterable
kurangi menimpa implementasi ini dan panggilan find
pada Iterator
, yang hanya berhenti iterasi sekali unsur ini ditemukan:
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
}
}
Akan lebih baik untuk tidak membuang pengecualian untuk Traversable
iterasi, tetapi itulah satu-satunya cara untuk mengulang sebagian saat menggunakan just foreach
.
Dari satu perspektif, Iterable
adalah sifat yang lebih menuntut / kuat, karena Anda dapat dengan mudah menerapkan foreach
menggunakan iterator
, tetapi Anda tidak dapat benar-benar menerapkan iterator
menggunakan foreach
.
Singkatnya, Iterable
menyediakan cara untuk menjeda, melanjutkan, atau menghentikan iterasi melalui stateful Iterator
. DenganTraversable
, itu semua atau tidak sama sekali (tanpa pengecualian untuk kontrol aliran).
Seringkali tidak masalah, dan Anda pasti menginginkan antarmuka yang lebih umum. Tetapi jika Anda membutuhkan lebih banyak kontrol yang disesuaikan atas iterasi, Anda akan memerlukan Iterator
, yang dapat Anda ambil dari file Iterable
.
Jawaban Daniel kedengarannya bagus. Biarkan saya melihat apakah saya bisa menjelaskannya dengan kata-kata saya sendiri.
Jadi Iterable dapat memberi Anda iterator, yang memungkinkan Anda melintasi elemen satu per satu (menggunakan next ()), dan berhenti dan pergi sesuka Anda. Untuk melakukan itu, iterator perlu menyimpan "penunjuk" internal ke posisi elemen. Namun Traversable memberi Anda metode, foreach, untuk melintasi semua elemen sekaligus tanpa henti.
Sesuatu seperti Range (1, 10) hanya perlu memiliki 2 integer sebagai status Traversable. Tapi Range (1, 10) sebagai Iterable memberi Anda iterator yang perlu menggunakan 3 integer untuk state, salah satunya adalah index.
Mempertimbangkan bahwa Traversable juga menawarkan foldLeft, foldRight, foreachnya perlu melintasi elemen dalam urutan yang diketahui dan tetap. Oleh karena itu, mungkin untuk mengimplementasikan iterator untuk Traversable. Misalnya def iterator = toList.iterator
Traversable
di Scala 2.13 (ini masih disimpan sebagai alias yang tidak digunakan lagiIterable
hingga 2.14)