2012-05-04 22 views
6

Şu anda "Scala'da Programlama" kitabında çalışarak Scala'yı öğreniyorum. Şimdiye kadar, orada (Java programcı perspektifinden) garip görünüyor her şey için güzel açıklamalar yapılmış, ancak Fibonacci dizisini oluşturmak için bir Akışı kullanarak bu bir örnek bana tür şaşkın bırakır adres:Scala'da Stream-cons # :: nasıl çevrilir?

def fibFrom(a: Int, b: Int): Stream[Int] = 
    a #:: fibFrom(b, a + b) 

Nasıl yapıdır Akışı bitti mi? Tabii ki #:: operatörü bunun için bir şekilde sorumludur. Anladığım kadarıyla, :'da bittiği için doğru-ilişkilendirici, ancak bu Stream'in oluşturulmasını açıklamıyor. Sanırım bir şekilde bir kurgana dolaylı olarak tercüme ediliyor ama neden ve nasıl olduğunu tam olarak göremiyorum.

Zaten Predef.scala ve LowPriorityImplicits.scala cevabını aradım ama şimdiye kadar hiç şans yok.

Beni aydınlatabilecek biri var mı? Doğru argüman üzerinde bir yöntem olarak çalışır böylece

cevap

8

Doğru ilişkisel geçerli:

fibFrom(b, a + b).#::(a) 

En azından o sözdizimsel yapmaya çalışır şeydir. Stream[Int]'un böyle bir yöntemi yoktur. Neyse ki, object Stream, bu yönteme sahip olan bazı ConsWrapper sınıfına örtülüdür ( code).

Yani, örtülü çözünürlük sonra ne elde şudur:

immutable.this.Stream.consWrapper(fibFrom(b, a + b)).#::(a) 
+0

Teşekkürler, işte bu kadar. Sunulan dönüşümlerin, dönüştürülmesi gereken sınıfın tamamlayıcı nesnesinde de tanımlanabileceğini unuttum. – rolve

+5

Scaladoc, muhtemelen bu kodlanmış tamamlayıcı içeriğin otomatik olarak eklenmesini sağlamalıdır. – Debilski

+2

Belki de Scala'da yeni olanlara işaret etmeliyiz ki _just_, doğru-ilişkilendirici değil. Ayrıca, ConsWrapper'ın, [ad-by] (https://github.com/scala/scala/blob/v2.10.3/src/library/scala/collection/immutable/Stream adresindeki # :: yi de uyguladığı da bilinmektedir. scala # L1042). yani "ConsWrapper" içinde "⇒" (tl: ⇒ Akış [A]) '' 'immutable.this.Stream.consWrapper (fibFrom (b, a + b)) 'ye çevirme. #: :(a)' anlamına gelir fibFrom (b, a + b) 'sadece erişildiğinde çağrılacak. – nicerobot

2

A Akış bir List benzer. Sadece başını ve akıntının geri kalanını bilir: Akıntı (kafa: T, kuyruk: Akıntı [T]). Fark, bir Akışın tembel olarak değerlendirildiğini. Yöntemin adının sonunda ':', yöntemin doğru çağrıştırıcı olduğunu söylüyor. Yani, bir # :: fibFrom (b, a + b) ifadesi, (derleyici tarafından) fibFrom'a (b, a + b). #: :(a) çevrilir.

+0

Teşekkürler, düşündüğüm buydu, ancak Stream nesnesinin nasıl oluşturulduğunu açıklamıyor. Eğer Stream bir '' 'metoduna sahip olsaydı, bu sanırım sonsuz bir tekrarlamaya sebep olurdu. – rolve

+0

# ::, Listede :: ile aynıdır. Ve evet sonsuz bir tekrarlamadır. Sadece istediğiniz eleman sayısını alırsınız. Bu, tembel olarak değerlendirildiğini söyleyerek ifade etmek istediğim şeydi. Bu, hesaplamaya ihtiyaç duyulduğunda hesaplanacağı anlamına gelir. –

+0

Tam olarak aynı değil, hayır. Eğer aynı olsaydı, orada sonsuz bir tekrarınız olurdu. Bunun yerine, # :: '(Akış değil, 'ConsWrapper' sınıfında tanımlanmıştır), tembel olarak değerlendirilen bir by-name parametresine sahiptir. – rolve

İlgili konular