scala转发参考扩展到定义

时间:2015-07-24 11:07:59

标签: scala

case object Empty extends Stream[Nothing]
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]

sealed trait Stream[+A] {

  def toList: List[A] = {
    val buf = new collection.mutable.ListBuffer[A]
    def go(s: Stream[A]): List[A] = s match {
      case Cons(h, t) =>
        buf += h()
        go(t())
      case _ => buf.toList
    }
    go(this)
  }

  def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = Stream.cons(hd, tl)

  def empty = Stream.empty

  def unfold[A, S](z: S)(f: S => Option[(A, S)]): Stream[A] = f(z) match {
    case Some((h,t)) => cons(h, unfold(t)(f))
    case None => empty
  }

  def take(n: Int): Stream[A] = unfold((this, n)) {
    case (Cons(h, t), 1) => Some((h(), (empty, 0)))
    case (Cons(h, t), n) if n > 1 => Some((h(), (t(), n-1)))
    case (Empty, 0) => None
  }
}

object Stream {

  def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = Cons(() => hd, () => tl)

  def empty[A]: Stream[A] = Empty

  val ones: Stream[Int] = Stream.cons(1, ones)
}

object StreamTest {
  def main(args: Array[String]) {

    //why compile error: forward reference extends over definition of value ones
    /*val ones: Stream[Int] = Stream.cons(1, ones)
    println(ones.take(5).toList)*/

    println(Stream.ones.take(5).toList)
  }
}

为什么编译错误?:正向引用扩展了对值的定义

在对象'Stream'中, val ones:Stream [Int] = Stream.scons(1,ones) 没问题

但是在主要方法中,它不行(但是......同样的合成!)

2 个答案:

答案 0 :(得分:8)

本地值不是成员。

对于您的测试代码,请执行以下操作:

object StreamTest extends App {
  //def main(args: Array[String]) {

    //why compile error: forward reference extends over definition of value ones
    val ones: Stream[Int] = Stream.cons(1, ones)
    println(ones.take(5).toList)

    println(Stream.ones.take(5).toList)
  //}
}

块中的限制是in the spec here,其他建议是在块中使它成为一个惰性val,这具有相同的效果。

答案 1 :(得分:1)

前向引用位于Cons[+A]...中,在此行中引用:

def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = Cons(() => hd, () => tl)

尝试移动

case object Empty extends Stream[Nothing]
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]

进入伴侣对象。