2

I am doing an exercise on the scala stream. I had from the book the following code. (I wrote the toList function)

  trait Stream2[+A] {
    def uncons: Option[(A, Stream2[A])]
    def isEmpty: Boolean = uncons.isEmpty

        def toList: List[A] = {
            def toListAcc(l:List[A], s:Stream2[A]):List[A]= {
                s.uncons match {
                    case Some((h, t)) => toListAcc(List(h) ++ l, t)
                    case None => l
                }
            }

            toListAcc(List(), this).reverse
        }



        def take(n: Int): Stream[A] = {
             ???}
  }

  object Stream2 {

    def empty[A]: Stream2[A] =
      new Stream2[A] { def uncons = None }

    def cons[A](hd: => A, tl: => Stream2[A]): Stream2[A] =
      new Stream2[A] {
        lazy val uncons = Some((hd, tl))
      }

    def apply[A](as: A*): Stream2[A] =
      if (as.isEmpty) empty
      else cons(as.head, apply(as.tail: _*))


  }


  val s = Stream2(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)  //> s  : chapter5.Stream2[Int] = chapter5$$anonfun$main$1$Stream2$3$$anon$2@782a
                                                  //| fee5
  s.toList                                        //> res0: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)


  }

Now I have to write the take function that creates a stream with only the first n elements. I am totally lost and I do not understand what do to. I think that my problems are due to the fact that I did not fully understand how a Stream2 object is created. I guess that this is related to the uncons function ( or maybe cons).

So finally I would like:

1) an explanation of how this code should work

2) To know if toList is written correctly in term of way to dial with lazy evaluation

3) the code for the function take or at least some hints to write it by myself.

Donbeo
  • 17,067
  • 37
  • 114
  • 188

1 Answers1

0

A possible solution with the implementation of the take and few other functions. The code is still rude and so a better answer is welcome

object chapter5 {
  println("Welcome to the Scala worksheet")       //> Welcome to the Scala worksheet

  trait Stream2[+A] {
    def uncons: Option[(A, Stream2[A])]
    def isEmpty: Boolean = uncons.isEmpty

    def toList: List[A] = {
      def toListAcc(l: List[A], s: Stream2[A]): List[A] = {
        s.uncons match {
          case Some((h, t)) => toListAcc(List(h) ++ l, t)
          case None         => l
        }
      }

      toListAcc(List(), this).reverse
    }

    def take(n: Int): Stream2[A] = {
      def takeAcc(n: Int, s: Stream2[A], acc: Stream2[A]): Stream2[A] =
        {
          if (n == 0) acc
          else {
            s.uncons match {
              case Some((h, t)) => takeAcc(n - 1, t, Stream2.cons(h, acc))
              case None         => acc

            }

          }
        }

      val sReverse = takeAcc(n, this, Stream2())
      takeAcc(n, sReverse, Stream2())

    }

    def foldRight[B](z: => B)(f: (A, => B) => B): B =
      uncons match {
        case Some((h, t)) => f(h, t.foldRight(z)(f))
        case None         => z
      }

    def exists(p: A => Boolean): Boolean =
      foldRight(false)((a, b) => p(a) || b)

    def map[B](f: A => B): Stream2[B] = {
      foldRight(Stream2[B]())((x, y) => Stream2.cons(f(x), y))
    }

        def forAll(p: A => Boolean): Boolean = {
            foldRight(true)((x, y) =>  p(x) && y)

        }

  }
  // end of trait

  object Stream2 {

    def empty[A]: Stream2[A] =
      new Stream2[A] { def uncons = None }

    def cons[A](hd: => A, tl: => Stream2[A]): Stream2[A] =
      new Stream2[A] {
        lazy val uncons = Some((hd, tl))
      }

    def apply[A](as: A*): Stream2[A] =
      if (as.isEmpty) empty
      else cons(as.head, apply(as.tail: _*))

  }
  //end of obj Stream2

  val s = Stream2(1, 2, 3, 4)                     //> s  : chapter5.Stream2[Int] = chapter5$$anonfun$main$1$Stream2$3$$anon$2@70c
                                                  //| 73be3
  s.toList                                        //> res0: List[Int] = List(1, 2, 3, 4)
  Stream2.cons(0, s).toList                       //> res1: List[Int] = List(0, 1, 2, 3, 4)

  s.take(5).toList                                //> res2: List[Int] = List(1, 2, 3, 4)

  s.foldRight(0)((x, y) => x + y)                 //> res3: Int = 10

    s.map(x=>x*x).toList                      //> res4: List[Int] = List(1, 4, 9, 16)

    s.forAll(x=>x%2==0)                       //> res5: Boolean = false
    s.forAll(x=> x>0)                         //> res6: Boolean = true




}
Donbeo
  • 17,067
  • 37
  • 114
  • 188