これを見て
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 }
やっぱ、そんな感じになるのか…。