Bu soruya baktım ama yine de Yinelenebilir ve Geçilebilir özellikler arasındaki farkı anlamadım. Biri açıklayabilir mi?
Yanıtlar:
Basitçe ifade etmek gerekirse, yineleyiciler durumu korurlar, geçişler yapmaz.
Bir Traversabletek özet yöntem var foreach. Aradığınızda foreach, koleksiyon geçilen işlevi tuttuğu tüm öğeleri birbiri ardına besleyecektir.
Öte yandan, bir Iterablehas as as abstract method iterator, bu da bir Iterator. Seçtiğiniz zamanda nextbir Iteratorsonraki öğeyi almak için bir çağırabilirsiniz . Siz bunu yapana kadar, koleksiyonun neresinde olduğunu ve sırada ne olduğunu takip etmesi gerekiyor.
Iterablegenişliyor Traversable, yani sanırım Traversables değil Iterables demek istiyorsun .
Traversablearayüze uymak, arayüze uyurken durumu korumayı gerektirmez Iterator.
TraversableIterableyineleme durumunu korumayan s . Bu oluyor Iteratoroluşturulan ve döndürdüğü Iterabledurumunu tutar.
Bunu üfleme ve emme arasındaki fark olarak düşünün.
Bir Traversables'yi foreachveya türetilmiş yöntemlerini çağırdığınızda , değerlerini işlevinize birer birer üfler - böylece yineleme üzerinde kontrol sahibi olur.
Bir Iteratordüşünce tarafından geri döndürüldüğünde, bir Iterablesonrakine ne zaman geçeceğinizi kendiniz kontrol ederek değerleri ondan emersiniz.
tl, dr Iterables olan Traversablesbu durum bilgisi üretebilirIterators
Öncelikle, bunun alt özelliği Iterableolduğunu bilin Traversable.
İkinci,
Traversableforeachher şey tarafından kullanılan yöntemin uygulanmasını gerektirir .
Iterableiteratorher şey tarafından kullanılan yöntemin uygulanmasını gerektirir .
Örneğin, uygulaması findiçin Traversablekullanımları foreach(anlama için bir cihaz aracılığıyla) ve atar BreakControltatmin edici bir unsur bulunduktan sonra bir yineleme durdurmak için durum.
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
}
}
Buna karşılık, Iterableçıkarma, bu uygulama ve aramaları geçersiz kılar findüzerinde Iteratoreleman bulunduğunda sadece yineleme durdurur:
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
}
}
TraversableYineleme için istisnalar atmamak güzel olurdu , ancak yalnızca kullanırken kısmen yinelemenin tek yolu budur foreach.
Bir bakış açısına göre, kullanmayı Iterablekolayca uygulayabileceğiniz için daha zorlu / güçlü özelliktir , ancak kullanmayı gerçekten uygulayamazsınız .foreachiteratoriteratorforeach
Özet olarak, Iterablebir durum bilgisi aracılığıyla yinelemeyi duraklatmanın, devam ettirmenin veya durdurmanın bir yolunu sağlar Iterator. İle Traversable, hepsi ya da hiçbiri (akış kontrolü için istisnalar hariç).
Çoğu zaman önemli değildir ve daha genel bir arayüz isteyeceksiniz. Ancak yineleme üzerinde daha özelleştirilmiş kontrole ihtiyacınız olursa Iterator, bir Iterable.
Daniel'in cevabı kulağa hoş geliyor. Bakalım kendi sözlerimle ifade edebilecek miyim?
Böylece, Yinelemeli size bir yineleyici verebilir, bu, öğeleri birer birer geçmenize (next () kullanarak) ve istediğiniz gibi durup gitmenize olanak tanır. Bunu yapmak için yineleyicinin, elemanın konumuna dahili bir "işaretçi" tutması gerekir. Ancak bir Traversable size foreach, tüm öğeleri aynı anda durmadan çaprazlama yöntemini verir.
Range (1, 10) gibi bir şey, Traversable olarak durum olarak yalnızca 2 tam sayıya sahip olmalıdır. Ancak Yinelenebilir olarak Range (1, 10) size durum için 3 tamsayı kullanması gereken bir yineleyici verir, bunlardan biri indeksdir.
Traversable'ın ayrıca foldLeft, foldRight da sunduğunu düşünürsek, foreach'in öğeleri bilinen ve sabit bir sırayla çaprazlaması gerekir. Bu nedenle, Traversable için bir yineleyici uygulamak mümkündür. Örneğin, def iterator = toList.iterator
Traversableiçinde Scala 2.13 (halen kaldırılmış bir takma ad olarak tutulurIterable2.14 kadar)