Scala 惰性集合增长

标签 scala collections lazy-evaluation

这个问题比较理论化。 我有一个对象,它包含一个私有(private)可变列表或映射,其增长仅是附加的。我相信我可以争辩说,对象本身是功能性的,功能上是透明的,而且从表面上看,是不可变的。例如我有

import scala.collection.mutable.Map

case class Foo(bar:String)

object FooContainer {
  private val foos = Map.empty[String, Foo]

  def getFoo(fooName:String) = foos.getOrElseUpdate(fooName, Foo(fooName))
}

我可以用列表做类似的情况。现在我想象要真正发挥作用,我需要确保线程安全,我想我可以简单地使用锁、同步或原子引用来做到这一点。我的问题是这是否是必要且充分的,这是一种常见的做法,这种行为是否有既定的模式?

最佳答案

我想说“功能性”这个词确实是错误的。上面显示的确切示例可以称为“纯”,因为它的输出仅由其输入定义,因此没有任何(可见的)副作用。但实际上它是不纯粹的,因为它隐藏了内部状态。

The function always evaluates the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change as program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices. Wikipedia

如果您使 Foo 类变得可变,那么明显的杂质就会消失:

case class Foo(bar:String) {
    private var mutable:Int = 1
    def setFoo(x:Int) = mutable = x
    def foo = mutable
}

Foo 类的可变性导致 getFoo 不纯:

scala> FooContainer.getFoo("test").foo
res5: Int = 1

scala> FooContainer.getFoo("bla").setFoo(5)

scala> FooContainer.getFoo("bla").foo
res7: Int = 5

为了使函数看起来是纯粹的,FooContainer.getFoo("bla").foo 必须始终返回相同的值。因此,所描述的构造的“纯度”充其量是脆弱的。

关于Scala 惰性集合增长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15359561/

相关文章:

scala - 在 Scala 中在运行时对协变和逆变类进行有效的类型转换

javascript - 收藏一定要有模型吗?

haskell - 为什么 foldr 可以处理 Haskell 中的无限列表,而 foldl 不行?

r - NSE lazyeval::lazy 与引用变量名时的替换

performance - 难以理解 Haskell 内存分配行为

scala - 在 Scala/Spark 中将纪元转换为日期时间

Scala Actor - 最糟糕的做法?

scala - 玩! : Does Slick's DDL replace Evolutions?

java - Spring Security方法规则: returned value contains a Collection

java - 使用 vavr 中的索引遍历列表