2015-07-24 13 views
6
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) 
    } 
} 

errore perché compilazione ?: riferimento in avanti estende definizione di quelle valorescala riferimento in avanti estende definizione

nella coppia oggetto 'flusso', quelli val: Flusso [Int] = Stream.scons (1, quelli) è ok

ma nel metodo principale, non è consentito (ma ... lo stesso materiale sintetico!)

+0

@mz eliminare il segno di commento (/ * * /) nel metodo principale, '/ * val: Stream [Int] = Stream.cons (1, ones) println (ones.take (5) .toList) */' – Curycu

risposta

7

Val locali non sono membri.

Per il vostro codice di prova, fare questo:

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

La restrizione in blocchi è formulata in the spec here, dove l'altro consiglio è quello di renderlo un val pigro nel blocco, che ha lo stesso effetto.

+0

funziona! senza il metodo principale, l'oggetto StreamTest viene eseguito ... forse la ragione è "estende l'app", penso. Anche l'approccio 'lazy val' funziona bene. la limitazione nel blocco è abbastanza interessante. Grazie! – Curycu

+0

'App' consente di eseguire l'inizializzatore da' main' ma si mantiene la semantica del template. –

1

Il riferimento in avanti è in Cons[+A]... cui viene fatto riferimento in questa linea:

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

tenta di spostare

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

nell'oggetto guidata.

+0

sposta' Vuoto, Contro' in 'oggetto Stream' e cambia' Cont = = Stream.Cons e Vuota => Stream.Empty' per eliminare gli errori di compilazione. Ma nulla cambia – Curycu

Problemi correlati