我正在完成《Scala 函数式编程》一书中的练习和概念。假设我需要定义一个常量函数,它按给定值返回无限流。
这是我的版本:
def constant[A](a: A): Stream[A] = Stream.cons(a, constant(a))
答案在 GitHub :
def constant[A](a: A): Stream[A] = {
lazy val tail: Stream[A] = Cons(() => a, () => tail)
tail
}
评论说后者比前者更有效,因为它只是一个引用自身的对象。 我无法理解这一点,任何帮助将不胜感激。 (对我蹩脚的英语感到抱歉:)
最佳答案
假设您以第一种方式定义constant
。现在,
constant(something)
这是一个 Cons
单元格,它引用了惰性值 something
和 constant(something)
Cons(() => something, () => constant(something))
现在,让我们尝试获取第 1000 个元素。我们需要评估尾部,因为我们需要比第一个元素更深入。因此,我们执行 constant(something)
,然后我们得到一个新 Cons
单元格,它看起来就像原来的一样:
Cons(() => something, () => constant(something))
我们尝试获取此Stream
的第999个元素。这是低效的,因为这个对象与之前的对象相同,所以我们只是浪费了时间来制作它。我们将继续浪费时间和内存来制作 1000 个相同的 Cons
单元。 (请原谅糟糕的绘图。)
现在,用第二种方式定义constant
。
constant(something)
{ lazy val self = Cons(something, self); self }
现在,您的Stream
仅具有对其自身的引用。获取此 Stream
的尾部不会创建新的 Cons
单元;它只是返回原始流(self.tail eq self
),这意味着您不会浪费任何内存,而且时间成本也会下降,因为您也不会浪费时间分配和填充该内存。
关于scala - scala 中的函数式编程 - 无限流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46900605/