【问题标题】:Scala Mutable Option?Scala可变选项?
【发布时间】:2014-12-16 00:23:42
【问题描述】:

我想要这样的东西:

private val cachedResponse = mutable.Option.empty[A]

def get: A = cachedResponse getOrElseUpdate db.findModel()

def update: Unit = {
  db.updateModel
  cachedResponse.empty()    // set it to None/Option.empty
}

我不是在寻找基于通用 HashMap 的记忆 like this。我尝试使用 var Option[A] 来实现它,但对我来说它看起来并不习惯:

private var cachedResponse: Option[A] = None

def get: A = cachedResponse getOrElse {
 cachedResponse = Option(db.findModel())
 cachedResponse.get
}

def update: Unit = {
  db.updateModel
  cachedResponse = None
}

【问题讨论】:

标签: scala scala-collections scala-option


【解决方案1】:

标准库中没有内置的。

使用包含不可变 Optionvar 是惯用的方法(假设您不能将其重写为根本不使用状态)。

否则,您应该构建自己的。这是实现的核心:

class MutableOpt[A] {
  private[this] var myValue: A = _
  private[this] var loaded = false
  private def valueEquals(o: Any) = myValue == o
  def get = if (loaded) myValue else throw new NoSuchElementException("MutableOpt")
  def set(a: A): this.type = { loaded = true; myValue = a; this }
  def getOrSet(a: => A): A = {
    if (!loaded) {
      myValue = a
      loaded = true
    }
    myValue
  }
  def isEmpty = !loaded
  def nonEmpty = loaded
  def foreach[U](f: A => U): Unit = if (loaded) f(myValue)
  def transform(f: A => A): this.type = { if (loaded) myValue = f(myValue); this }
  def clear(): this.type = { loaded = false; this }
  def toOption = if (loaded) Some(myValue) else None
  override def toString = if (loaded) "MutableOpt("+myValue.toString+")" else "MutableOpt()"
  override def hashCode = if (loaded) myValue.hashCode else 1751
  override def equals(o: Any) = o match {
    case m: MutableOpt[_] =>
      (isEmpty && m.isEmpty) || (nonEmpty && m.nonEmpty && m.valueEquals(myValue))
    case _ => false
  }
}
object MutableOpt {
  def from[A](o: Option[A]) = {
    val m = new MutableOpt[A]
    o match {
      case Some(a) => m set a
      case _ =>
    }
    m
  }
}

如果使用 REPL,请与 :paste 一起定义。

【讨论】:

  • LGTM。感谢分享。但是,在多线程环境中,getrSet 中可能存在一些竞争条件..
  • 没错,这正是不变性优于可变性的优势之一。
  • @wrick - 绝对,就像几乎所有可变的东西一样。您可以将所有操作设为原子操作,但性能会受到影响。
猜你喜欢
  • 2012-01-09
  • 2013-04-10
  • 1970-01-01
  • 1970-01-01
  • 2014-11-28
  • 2018-05-04
  • 2017-09-20
  • 2018-12-19
  • 1970-01-01
相关资源
最近更新 更多