为什么constant()解决方案比“FP in Scala”5.8中更容易的解决方
我正在阅读“
Scala中的FP”一书中的练习5.8,问题是:
“稍微概括一下函数常量,返回给定值的无限流.” def constant[A](a: A): Stream[A] 我的解决方案是: def constant[A](a: A): Stream[A] = Stream.cons(a,constant(a)) 我指的是标准解决方案,它是: // This is more efficient than `cons(a,constant(a))` since it's just // one object referencing itself. def constant[A](a: A): Stream[A] = { lazy val tail: Stream[A] = Cons(() => a,() => tail) tail } 其中说“效率更高”,见here. 我能知道它为什么效率更高? Streams中的cons构造函数AFAIK已经将头部和尾部标记为懒惰: def cons[A](hd: => A,tl: => Stream[A]): Stream[A] = { lazy val head = hd lazy val tail = tl Cons(() => head,() => tail) } 为什么我们仍然需要将尾巴标记为懒惰?我不太明白这一点. 解决方法
这更像是对@ElBaulP答案的评论,而不是对自己权利的回答,但对于评论来说它太大了.
我认为你错过了优化的根源,即使它已在上面的评论中明确说明.常量中的val尾部是惰性的这一事实是一个实现细节,或者说是使得优化的主要来源成为可能的技巧.优化的主要来源是尾部是自引用的. 暂时让我们摆脱所有懒惰的东西.假设Cons被定义为 case class Cons[+A](h: A,t: () => Stream[A]) extends Stream[A] 让我们将常量定义为 def constant[A](a: A): Stream[A] = { val tailFunc: () => Stream[A] = () => tail val tail: Stream[A] = Cons(a,tailFunc) tail } 是的,这是一个语法上无效的程序,因为tailFunc只在下一行使用tail定义.但想象Scala可以编译它.我想现在很明显,这样的常量实现只会在每次调用时创建一个Cons类实例,无论你多久尝试迭代返回的流,都会使用该实例. 延迟允许的定义尾部只是使代码在逻辑上等同于上面的编译而没有错误.从实现的角度来看,它类似于: class Lazy[A](var value:A) def constant[A](a: A): Stream[A] = { val lazyTail: Lazy[Stream[A]] = new Lazy(null) // this tailFunc works because lazyTail is already fixed and can be safely // captured although lazyTail.value will be changed val tailFunc: () => Stream[A] = () => lazyTail.value lazyTail.value = new Stream(a,tailFunc) lazyTail.value } 这个代码与许多细节中的实际延迟实现并不完全匹配,因为它实际上很渴望,但我认为它表明你并不需要懒惰来进行优化工作(但是以使用var为代价,Scala编译器无论如何都会这样做在其真实,更复杂的懒惰实现中). 在你天真的实施中 def constant[A](a: A): Stream[A] = Stream.cons(a,constant(a)) 懒惰的tail评估允许你不会因堆栈溢出而立即失败,因为从它自身的递归调用常量.但是当你执行常量(无论).tail时,尾部正在被评估,因此再次调用常量方法并创建一个新的Cons对象.每次在新头上调用尾部时都会发生这种情况. 为了再次重新声明它,lazy val tail只是一个允许尾部在创建时引用自身的技巧,而真正重要的部分是tail引用自身的事实,它允许只使用一个对象进行迭代而不是每个对象一个对象下一个.tail电话. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- twitter-bootstrap – 在Laravel 4中使用Bootstrap的最佳方
- 1.2、Bootstrap V4自学之路------起步---下载
- Angular2 – ngZone – google.maps不会触发更改检测
- [angularjs] angularjs系列笔记(一)简介
- 模态对话框 – Bootstrap Modal Focus无法正常工作
- D o t N e t 相关资源 [更新中]
- bootstrap Table options [API]
- 一篇文章学会shell工具篇之sed
- scala – 我的API都是返回Future [Option [T]],如何在comp-
- angularjs – 无法实例化控制器Angular New Router