美文网首页
严格求值和惰性求值(1)

严格求值和惰性求值(1)

作者: 吐思圈 | 来源:发表于2018-02-25 22:57 被阅读0次

非严格求值是函数的一种属性,称一个函数是非严格求值的意思是这个函数可以选择不对它的一个或者多个参数求值;相反,严格求值的函数总是对它的参数求值。在Scala中除非明确声明,否则任何函数都是严格求值的。
惰性列表:

sealed trait Stream[+A]

case object Empty extends Stream[Nothing]

case class Cons[+A](head: () => A, tail: () => Stream[A]) extends Stream[A]

object Stream {
  
  def empty[A]: Stream[A] = Empty
  
  def cons[A](h: => A, t: => Stream[A]): Stream[A] = {
    lazy val head = h
    lazy val tail = t
    Cons(() => head, () => tail)
  }

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

练习 5.1
写一个可将Stream转换成List的函数,它会被强制求值。

  def toList: List[A] = this match {
    case Empty => Nil
    case Cons(h, t) => h() :: t().toList  
  }

练习 5.2
写一个take(n)函数返回Stream中前n个元素;写一个函数drop(n)返回第n个元素之后的所有元素

   def take(n: Int): Stream[A] = n match {
    case m if m <= 0 => Empty
    case _ => this match {
      case Empty => Empty
      case Cons(h, t) => Cons(h, () => t().take(n - 1))
    }
  }

  def drop(n: Int): Stream[A] = n match {
    case m if m <= 0 => this
    case _ => this match {
      case Empty => Empty
      case Cons(h, t) => t().drop(n - 1)
    }
  }

练习 5.3
写一个函数takeWhile返回从起始元素连续满足给定断言的所有元素。

  def takeWhile(f: A => Boolean): Stream[A] = this match {
    case Empty => Empty
    case Cons(h, t) => if (f(h())) Cons(h, () => t().takeWhile(f)) else t().takeWhile(f)
  }

练习 5.4
实现一个forAll函数,检查Stream中所有元素是否与给定的断言匹配。遇到不匹配的值应该立即终止遍历。

  def foldRight[B](b: => B)(f: (A, => B) => B): B = this match {
    case Empty => b
    case Cons(h, t) => f(h(), t().foldRight(b)(f))  
  }
  
  def forAll(f: A => Boolean): Boolean = this match {
    case Cons(h, t) => f(h()) && t().forAll(f)
    case _ => true
  }
  
  def forAll1(f: A => Boolean): Boolean =
    foldRight(true)((a, b) => f(a) && b)

练习 5.5
使用foldRight实现takeWhile。

  import Stream._

  def takeWhile1(f: A => Boolean): Stream[A] =
    foldRight(empty[A]){(a, b) =>
      if (f(a)) cons(a, b)
      else b
    }

练习 5.6
使用foldRight实现headOption。

  def headOption: Option[A] = this match {
    case Empty => None
    case Cons(h, t) => Some(h())
  }

  def headOption1: Option[A] = {
    val init: Option[A] = None
    foldRight(init){(a, _) =>
      Some(a)
    }
  }

练习 5.7
用foldRight实现map、filter、append和flatMap,append方法参数应该是非严格求值的。

  def map[B](f: A => B): Stream[B] = this match {
    case Empty => Empty
    case Cons(h, t) => cons(f(h()), t().map(f))
  }
  
  def map1[B](f: A => B): Stream[B] =
    foldRight(empty[B])((a, b) => cons(f(a), b))

  def filter(f: A => Boolean): Stream[A] = this match {
    case Empty => Empty
    case Cons(h, t) =>
      if (f(h())) cons(h(), t().filter(f)) else t().filter(f)
  }
  
  def filter1(f: A => Boolean): Stream[A] =
    foldRight(empty[A])((a, b) => if (f(a)) cons(a, b) else b)

  def append[B >: A](s: => Stream[B]): Stream[B] = this match {
    case Empty => s
    case Cons(h, t) => cons(h(), t().append(s))
  }
  
  def append1[B >: A](s: => Stream[B]): Stream[B] =
    foldRight(s)((a, b) => cons(a, b))

  def flatMap[B >: A](f: A => Stream[B]): Stream[B] = this match {
    case Empty => Empty
    case Cons(h, t) => f(h()).append(t().flatMap(f))
  }

  def flatMap1[B >: A](f: A => Stream[B]): Stream[B] =
    foldRight(empty[B])((a, b) => f(a).append(b))

相关文章

  • 严格求值和惰性求值(1)

    非严格求值是函数的一种属性,称一个函数是非严格求值的意思是这个函数可以选择不对它的一个或者多个参数求值;相反,严格...

  • 严格求值和惰性求值(2)

    无限流与共递归因为具有增量性质,我们所写的函数也适用于无限流,这里是一个由1组成的无限流的例子: 尽管ones是无...

  • Swift Collection 中的 lazy 作用

    惰性求值 惰性求值常见于函数式编程中,也有人把惰性求值翻译成延迟求值(Lazy Evaluation)。它的目的是...

  • 4.2 Variations on a Scheme: Lazy

    在元循环求值器的基础上,我们能够实现变体形式 惰性求值(lazy evaluation) 器。惰性求值器能够将程式...

  • Swift 之惰性求值

    Swift 之惰性求值 在 Haskell 中的函数有一个特性 从而引出一个概念 惰性求值 下面有段 分析 惰性求...

  • Python中的优化:惰性求值详解

    惰性求值,也就是延迟求值,表达式不会在它被绑定到变量之后就立即求值,而是等用到时再求值。这个特性可以解决一些巨大甚...

  • 什么是惰性求值?

    表达式不在它被绑定到变量之后就立即求值,而是在该值被取用的时候求值 参考 惰性求值 - 维基百科,自由的百科全书

  • 利用 Lambda 表达式实现 Java 中的惰性求值

    Java 中惰性求值的潜能,完全被忽视了(在语言层面上,它仅被用来实现短路求值)。更先进的语言,如 Scala,区...

  • 【r<-高级】内部机制

    内容: 惰性求值 (Lazy evaluation)复制-修改机制 (Copy-on-modify mechani...

  • Java 尾递归

    知识点 尾递归 惰性求值 java8 : lambda Stream 柯里化

网友评论

      本文标题:严格求值和惰性求值(1)

      本文链接:https://www.haomeiwen.com/subject/zzdfxftx.html