Stream vs Views vs Yineleyiciler


136

Skala'daki Akışlar, Görünümler (SeqView) ve Yineleyiciler arasındaki farklar nelerdir? Bu benim anlayışım:

  • Hepsi tembel listeler.
  • Akışlar değerleri önbelleğe alır.
  • Yineleyiciler yalnızca bir kez kullanılabilir mi? Başa dönüp değeri tekrar değerlendiremiyor musunuz?
  • Görünümün değerleri önbelleğe alınmaz, ancak bunları tekrar tekrar değerlendirebilirsiniz?

Öyleyse yığın alanından tasarruf etmek istersem yineleyicileri (listeyi tekrar geçmeyeceğim) veya görünümleri kullanmalı mıyım? Teşekkürler.


7
Bunu daha önce cevapladım, ama nasıl bulabilirim? iç çekiş ...
Daniel C.Sobral

Yanıtlar:


182

Birincisi, hepsi katı değil . Bu, işlevlerle ilgili belirli bir matematiksel anlama sahiptir, ancak temel olarak, önceden değil, talep üzerine hesaplandıkları anlamına gelir.

Streamgerçekten de tembel bir liste. Aslında, Scala, bir Streambir ise Listkimin tailbir olduğunu lazy val. Hesaplandıktan sonra, bir değer hesaplanmış olarak kalır ve tekrar kullanılır. Veya, dediğin gibi, değerler önbelleğe alınır.

Bir Iterator, yalnızca bir kez kullanılabilir, çünkü kendi içinde bir koleksiyon değil, bir koleksiyona geçiş göstergesidir . Ne Scala o özel kılan gibi dönüşümü uygulayabileceğiniz gerçektir mapve filterve sadece yeni olsun Iteratorbir sonraki element için sorduğunuzda sadece bu dönüşümleri uygulanacağı.

Scala, sıfırlanabilen yineleyiciler sağlardı, ancak genel olarak desteklenmesi çok zordur ve 2.8.0 sürümünü yapmadılar.

Görünümlerin bir veritabanı görünümü gibi görüntülenmesi amaçlanmıştır. Bir "sanal" koleksiyon üretmek için bir koleksiyon için geçerli olan bir dönüşüm serisidir. Söylediğiniz gibi, tüm dönüşümleri her getirmeniz gerektiğinde tüm dönüşümler yeniden uygulanır.

Hem Iteratorgörüntüler hem de görüntüler mükemmel bellek özelliklerine sahiptir. Streamgüzeldir, ancak Scala'da asıl yararı sonsuz diziler yazmaktır (özellikle özyinelemeli olarak tanımlanan diziler). Bir edebilir tüm tutarak önlemek Streamemin onun bir başvuru tutmayız yaparak, olsa da, bellekte head(örneğin, kullanarak defyerine valtanımlamak için Stream).

Görüşlerin yol açtığı cezalar nedeniyle, genellikle forcedönüşümleri uyguladıktan sonra veya görüşün toplam boyutuna kıyasla yalnızca birkaç öğenin getirilmesi bekleniyorsa bir görünüm olarak saklanmalıdır.


10
Iteratorsonsuzluğu araştırmak için de oldukça kullanışlıdır ve genellikle mümkün olduğunda akışlara tercih ederim. Akarsulardaki gerçek fayda, daha önce erişilen değerlerin önbelleğe alınmasıdır; bu, önceki değerler açısından tanımlanan fibonacci dizisi gibi bir şey uygulamaya çalışırken ciddi bir nimettir.
Kevin Wright

5
Fibonacci, sadece son 2 değere ihtiyaç duyduğundan ve tüm akışı korumak bir israf olduğundan mükemmel bir örnektir. Ackermann işlevi muhtemelen kanonik örnektir.
Jürgen Strobel

4
@ JürgenStrobel Ackermann, akışların endeksli erişimi O (n) olduğundan berbat bir performansla sonuçlanacaktır. Fakat fibonacci'ye katılıyorum.
Daniel C. Sobral

9
Ah doğru. Bu, Stream'i herhangi bir önbellekleme yaklaşımı için kötü bir seçim haline getirir.
Jürgen Strobel

7
Bu cevap çok açık, belgelerin bir parçası olmalı ... oh, aslında öyle! Teşekkürler Daniel docs.scala-lang.org/tutorials/FAQ/stream-view-iterator.html
Svend
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.