Izb*_*gen 5 functional-programming scala
我正在关注《 Scala中的函数编程》一书。这是Stream定义和函数的代码片段,这些代码片段constant使用智能构造函数并使用来构造unfold:
sealed trait Stream[+A]
case object Empty extends Stream[Nothing]
case class Cons[+A](h: () => A, tl: () => Stream[A]) extends Stream[A]
object Stream {
def cons[A](h: => A, tl: => Stream[A]): Stream[A] = {
lazy val head = h
lazy val tail = tl
Cons(() => head, () => tail)
}
def empty[A]: Stream[A] = Empty
def constant[A](a: A): Stream[A] = cons(a, constant(a))
def unfold[A, S](z: S)(f: S => Option[(A, S)]): Stream[A] =
f(z).fold(empty[A])(x => cons(x._1, unfold(x._2)(f)))
def constantViaUnfold[A](a: A): Stream[A] = unfold(a)(x => Some((x, x)))
}
Run Code Online (Sandbox Code Playgroud)
有一个脚注说:
使用
unfold定义constant意味着我们不会像递归定义那样获得共享。即使我们遍历遍历它时,递归定义也会消耗常量内存,而基于展开的实现则不会。在使用流进行编程时,保留共享并不是我们通常所依赖的东西,因为它非常微妙,并且不受类型跟踪。例如,即使呼叫偶数,共享也会被破坏xs.map(x => x).
作者在说我们没有分享时是什么意思?究竟共享了什么,为什么它没有保留在unfold版本中?同样,关于恒定内存消耗的句子也不清楚。
假设您创建了一个这样的新列表:
val n0 = Nil //List()
val n1 = 1 :: n0 //List(1)
val n2 = 2 :: n1 //List(2,1)
val n3 = 3 :: n2 //List(3,2,1)
Run Code Online (Sandbox Code Playgroud)
如果你建立一个这样的列表,可以很容易地通知,N3是真的N2与3前置和N2只是N1与2前置等,所以参考1被共享由N1,N2和N3和参考2被共享n2和 n2等。你也可以这样写:
Cons(3, Cons(2, Cons(1, Nil)))
Run Code Online (Sandbox Code Playgroud)
在FPinS的示例中,当您递归创建Stream时,情况也是如此。You Stream是从嵌套的Cons构建的,每个子流都与其父流共享元素。因此,当创建下一个Stream时,它只是用新元素将旧的Stream包裹在Cons 中。但是由于Stream是惰性的,因此所有Cons层次结构的构建只有在您实现它时才会完成,例如通过调用toList。
像这样构建流也会使您持续消耗内存,因为从前一个流创建下一个流只会为新元素消耗内存。
为什么它不是一个案例unfold?因为它以“其他方式”构建 Stream。所以它是这样的:
Cons(x, next_iteration_of_unfold) //1st iteration
Cons(x, Cons(x, next_iteration_of_unfold)) //2nd iteration
Cons(x, Cons(x, Cons(x, next_iteration_of_unfold))) //3rd iteration, etc.
Run Code Online (Sandbox Code Playgroud)
所以正如你所看到的,没有什么可以共享的。
编辑:
您可以通过调用本书的take最终实现并添加toString到Cons以下内容来查看物化流的外观:
override def toString: String = s"Cons(${h()}, ${tl()})"
Run Code Online (Sandbox Code Playgroud)
进而:
Stream.ones.take(3)
Run Code Online (Sandbox Code Playgroud)
你会看见:
Cons(1, Cons(1, Cons(1, Empty)))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
119 次 |
| 最近记录: |