簡體   English   中英

在斯卡拉的溪流

[英]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關鍵字實例化案例類的方式,因為編譯器會自動為您生成applyunapply

如果我們看一個更簡單的復制:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM