CLOVER🍀

That was when it all began.

getOrElseUpdateOpt?

これを見て
http://d.hatena.ne.jp/nanjakkun/20130412/1365772017

ちょっと面白そうだったので、書いてみました。

思いついたのは、こんなパターンくらい。

trait MyMap[A, B] extends Map[A, B] {
  def getOrElseUpdateOpt1(key: A, defaultValue: => Option[B]): Option[B] =
    get(key) match {
      case s @ Some(_) => s
      case _ => defaultValue map { v => update(key, v); v }
    }

  def getOrElseUpdateOpt2(key: A, defaultValue: => Option[B]): Option[B] =
    (get(key), defaultValue) match {
      case (s @ Some(_), _) => s
      case (_, s @ Some(v)) => update(key, v); s
      case _ => None
    }

  def getOrElseUpdateOpt3(key: A, defaultValue: => Option[B]): Option[B] =
    Option(getOrElse(key,
                     defaultValue.map { v => update(key, v); v }
                       .getOrElse(null.asInstanceOf[B])))
}

自分を更新するという副作用が入る分だけ、そこがどうしても微妙なところに見えますね。

これを書いた後に、本家のMapLike#getOrElseUpdateを見てみました。

  def getOrElseUpdate(key: A, op: => B): B =
    get(key) match {
      case Some(v) => v
      case None => val d = op; this(key) = d; d
    }

やっぱ、そんな感じになるのか…。