scala – 如何在递归上下文中解释延迟?
这是
FPIS的代码
object test2 { //a naive IO monad sealed trait IO[A] { self => def run: A def map[B](f: A => B): IO[B] = new IO[B] { def run = f(self.run) } def flatMap[B](f: A => IO[B]): IO[B] = { println("calling IO.flatMap") new IO[B] { def run = { println("calling run from flatMap result") f(self.run).run } } } } object IO { def unit[A](a: => A): IO[A] = new IO[A] { def run = a } def apply[A](a: => A): IO[A] = unit(a) // syntax for IO { .. } } //composer in question def forever[A,B](a: IO[A]): IO[B] = { lazy val t: IO[B] = a flatMap (_ => t) t } def PrintLine(msg: String) = IO { println(msg) } def say = forever(PrintLine("Still Going..")).run } 在堆栈溢出之前,test2.say将打印数千个“Still Going”.但我不确切知道这是怎么发生的. 输出如下所示: … //重复直到堆栈溢出 当函数永远返回时,懒惰的val是否被完全计算(缓存)? =========== 我手动尝试永远[单位,双],永远[单位,字符串]等,这一切都有效.这感觉很聪明. 解决方法
是
在你的情况下没用.在以下情况下它可能很有用: def repeat(n: Int): Seq[Int] { lazy val expensive = "some expensive computation" Seq.fill(n)(expensive) // when n == 0,the 'expensive' computation will be skipped // when n > 1,the 'expensive' computation will only be computed once }
在您提供最小,完整和可验证的示例之前无法发表评论,例如@Yuval Itzchakov说 更新时间2017/04/19 好吧,我需要纠正自己:-)在你的情况下,由于递归引用回到自身,所以需要lazy val. 为了解释你的观察,让我们尝试扩展forever(a).run调用: >永远(a)扩展到 因为t是惰性的,所以2和3中的flatMap和新IO [B]只被调用一次,然后“缓存”以便重用. 在3上调用run()时,你会在t.run上开始递归,从而得到你观察到的结果. 不完全确定您的要求,但永远的非堆栈版本可以实现如下: def forever[A,B](a: IO[A]): IO[B] = { new IO[B] { @tailrec override def run: B = { a.run run } } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 在bash中将参数传递给别名
- SHELL训练营--day29_shell练习86-90
- AngularJS ngOptions排序数组
- 什么是更多Scala惯用语:trait TraitA扩展TraitB或trait Tr
- webpack AngularCompilerPlugin hostReplacementPaths选项不
- axis,jax-ws,xfire客户端调用分析,以及webservice万能客户端
- bootstrap-4 – Webpack安装Bootstrap – 缺少popper.js.ma
- bash – 搜索复制的作业
- openldap 2.4 centos7 配置
- 为Haskell平台(标准库)生成ctags,专门用于前奏