Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scala forward reference extends over definition

Tags:

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)
  }
}

why compile error?: forward reference extends over definition of value ones

in pair object 'Stream', val ones: Stream[Int] = Stream.scons(1, ones) is ok

but in main method, it's not ok (but... same synthetics!)

like image 238
Curycu Avatar asked Jul 24 '15 11:07

Curycu


2 Answers

Local vals are not members.

For your test code, do this:

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)
  //}
}

The restriction in blocks is worded in the spec here, where the other advice is to make it a lazy val in the block, which has the same effect.

like image 177
som-snytt Avatar answered Nov 03 '22 12:11

som-snytt


The forward reference is in Cons[+A]...which is referenced in this line:

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

Try to move

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

into the companion object.

like image 26
Sascha Kolberg Avatar answered Nov 03 '22 11:11

Sascha Kolberg