【问题标题】:Exercise on scala Stream class and theoretical explanationscala Stream类练习及理论讲解
【发布时间】:2015-05-09 05:53:23
【问题描述】:

我正在对 scala 流进行练习。我从书中得到了以下代码。 (我写了toList函数)

  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)


  }

现在我必须编写一个 take 函数来创建一个只有前 n 个元素的流。我完全迷失了,我不明白该怎么做。我认为我的问题是由于我没有完全理解 Stream2 对象是如何创建的。我猜这与uncons 函数(或者可能是cons)有关。

所以最后我想:

1) 解释这段代码应该如何工作

2) 了解 toList 是否正确地写入了惰性求值拨号方式

3) 函数的代码需要或至少有一些提示是我自己编写的。

【问题讨论】:

    标签: scala stream lazy-evaluation


    【解决方案1】:

    实现 take 和其他一些功能的可能解决方案。该代码仍然很粗鲁,因此欢迎提供更好的答案

    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
    
    
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多