Scala 的严格求值和惰性求值

Scala 的严格求值和惰性求值

惰性求值

对一系列的转换融合成单个函数面产生临时数据结构

通过使用非严格求值(non-strictness),也叫惰性求值,来实现这种自动循环的融合物。非严格求值是一项提升函数式编程效率的模块化基础技术

严格和非严格函数

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

在 Scala 中,除非明确声明,否则任何函数都是严格求值的

thunk

通常一个表达式的未求值形式称为thunk

使用传名函数的方式,Scala 会负责为我们将表达式包装为 thunk

对一个 val 声明的变量添加 lazy 修饰符,将导致 Scala 延迟对这个变量求值,直到它第一次被应用的时候。它会缓存结果,在后续应用的地方不会触发重复求值

Scala 中非严格求值的函数接受的参数是传名参数(by name)而非传值参数(by value)

关注分离(separation of concerns)

就是将计算的描述与实际运行分开。这也是函数式编程的主题之一

一等循环(first-class loops)

可以使用高阶函数,如 map、filter 等组合

无限流(infinite stream)与共递归(corecursive)

无限流容易写出永不结束或线程栈不安全的表达式

递归函数由不断地对更小范围的输入参数进行递归调用而结束(terminate);而共递归函数只要保持生产数据不需要结束,这意味着总是可以在一个有限的时间段里对更多的结果求值。共递归有时也被成为守护递归(guarded recursion),生产能力有时也被称为共结束(cotermination)

共递归的例子:

  def unfold[A, S](z: S)(f: S => Option[(A, S)]): Stream[A] = {
    f(z) match {
      case Some((a, s)) => cons(a, unfold(s)(f))
      case None => empty
    }
  }

如果能够理解unfoldfoldRightscanRight,那么该部分的内容就算理解透了

  def foldRight[B](z: => B)(f: (A, => B) => B): B =
    this match {
      case Cons(h, t) => f(h(), t().foldRight(z)(f)) // If `f` doesn't evaluate its second argument, the recursion never occurs.
      case _ => z
    }
	
  def scanRight[B](z: B)(f: (A, => B) => B): Stream[B] =
    foldRight((z, Stream(z)))((a, p0) => {
      lazy val p1 = p0
      val b2 = f(a, p1._1)
      (b2, cons(b2, p1._2))
    })._2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GettingReal

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值