2012-05-04 11 views
6

私は現在、 "Programming in Scala"の書籍を通じてScalaを学習しています。これまでのところ、(Javaプログラマの視点から)奇妙に見えるすべてのもののための素晴らしい説明がありましたが、フィボナッチ数列を生成するためのストリームを使用して、この一例は、一種の困惑私の葉:Stream-cons#はどのようにScalaで翻訳されていますか?

建設でどのように
def fibFrom(a: Int, b: Int): Stream[Int] = 
    a #:: fibFrom(b, a + b) 

ストリームの完了?もちろん、オペレータは#::です。私はそれが:で終わるので、右結合であると理解しますが、それはストリームの作成を説明しません。暗黙のうちに何らかの形でコンストラクタに変換されると思いますが、私はなぜ、どのように正確に見えません。

私は既にPredef.scalaLowPriorityImplicits.scalaで答えを探しましたが、これまでのところ運がありません。

誰でも私を啓発できますか?

答えて

8

それは右引数にメソッドとして働くので、それは右結合である:

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

は、少なくともそれはそれは文法的に行おうとするものです。 Stream[Int]にはこのようなメソッドはありません。幸運にも、object Streamは、このメソッド(code)を持ついくつかのクラスConsWrapperに暗黙的に属しています。

だから、あなたは暗黙的な解決後に得るものは以下です:

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

ありがとうございました。暗黙的な変換は、変換すべきクラスのコンパニオンオブジェクトで定義することもできないことを忘れていました。 – rolve

+5

Scaladocにはおそらくこれらのハードコーディングされたコンパニオンインプリシットが自動的に組み込まれるべきです。 – Debilski

+2

Scalaに新しく追加されたことは、正しい連想ではないことを指摘するかもしれません。また、ConsWrapperは[名前による呼び出し]として '#::'を実装しています(https://github.com/scala/scala/blob/v2.10.3/src/library/scala/collection/immutable/Stream。スカラ#L1042)。 #::(a) 'は、ConsWrapper(tl:⇒Stream [A])の'⇒'を 'immutable.this.Stream.consWrapper(fibFrom(b、a + b) 'fibFrom(b、a + b)'はアクセスされたときにのみ呼び出されます。 – nicerobot

2

A Streamがリストに似ています。それはその頭部とストリームの残りの部分だけを知っている:ストリーム(頭:T、テール:ストリーム[T])。違いは、ストリームが遅れて評価されることです。メソッドの名前の最後にある ':'は、メソッドが正しい結合であることを示します。したがって、式a#:: fibFrom(b、a + b)は、(コンパイラによって)fibFrom(b、a + b)。#::(a)に変換されます。

+0

ありがとう、それは私が考えたものですが、Streamオブジェクトの作成方法については説明していません。 Streamにメソッド '#::'があれば、これは無限再帰を引き起こすでしょう。 – rolve

+0

#::はListと同じです。そして、それは無限回帰です。あなたは、あなたが望む要素の数を取るだけです。それは怠惰に評価されていると言って表現したかったのです。これは、コンピューティングの必要があるときに計算されることを意味します。 –

+0

全く同じではありません。それが同じであれば、そこには無限回帰があります。代わりに '#::'(クラス 'ConsWrapper'で定義され、Stream!では定義されていません)には、lazilyに評価されるby-nameパラメータがあります。 – rolve

関連する問題