[英]Streams in Scala
我有一段代碼正在計算一些序列:
object Problem7 extends App {
lazy val ps: Stream[Int] = 2 #:: Stream.from(3).filter(i =>
ps.takeWhile(j => j * j <= i).forall(i % _ > 0))
val r = ps(10000)
println(r)
}
這里的ps
是類型Stream的集合,實際上它是一個變量,但是怎么可能像這樣ps(10000)
那樣調用它,因為它不是任何方法,而且我還有一個表達式val fs:Stream[Int] = 0 #:: fs.scanLeft(1)(_ + _)
,在這里我對於如何在變量本身中調用fs.scanLeft(1)(_+_)
也有點含糊不清。
這里的
ps
是集合Stream的類型,實際上它是一個變量,但是像這樣的ps(10000)怎么可能調用它而不是任何方法
可以調用ps(10000)
因為Stream
具有apply
方法(繼承自LinerSeqOptimized
):
/** Selects an element by its index in the $coll.
* Note: the execution of `apply` may take time proportial to the index value.
* @throws `IndexOutOfBoundsException` if `idx` does not satisfy `0 <= idx < length`.
*/
def apply(n: Int): A = {
val rest = drop(n)
if (n < 0 || rest.isEmpty) throw new IndexOutOfBoundsException("" + n)
rest.head
}
在Scala中對任何對象調用()
將使編譯器在該對象上尋找apply
方法。 這類似於不使用new
關鍵字實例化案例類的方式,因為編譯器會自動為您生成apply
和unapply
。
如果我們看一個更簡單的復制:
def main(args: Array[String]): Unit = {
val ps: Stream[Int] = Stream.from(1, 1)
val r = ps(1)
println(r)
}
編譯器實際上在做:
val r = ps.apply(1)
apply
集合通常在索引i
處查找元素:
scala> val ps: Stream[Int] = Stream.from(1, 1)
ps: Stream[Int] = Stream(1, ?)
scala> val r = ps(1)
r: Int = 2
scala> val x = ps.apply(1)
x: Int = 2
如果您實際上想查看編譯器生成的內容:
object Problem7 extends Object {
def main(args: Array[String]): Unit = {
val ps: scala.collection.immutable.Stream = scala.`package`.Stream().from(1, 1);
val r: Int = scala.Int.unbox(ps.apply(1));
scala.this.Predef.println(scala.Int.box(r))
};
def <init>(): Problem7.type = {
Problem7.super.<init>();
()
}
}
}
對於問題的第二部分,
lazy val fs:Stream[Int] = 0 #:: fs.scanLeft(1)(_ + _)
#::是cons運算符Stream.cons,用於構造流。 ConsWrapper的參數是一個按名稱命名的參數,因此它是惰性計算的。
因此,在#::運算符之后引用fs是有效的。 我認為我們必須將val更改為lazy val,否則scala編譯器拋出的前向引用將擴展到值fs的定義上。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.