scalaz の |> みたいに、自身をpimpして、かつFunction1ではなくPartialFunction[A,B] を受け取って、Option[B]を返すものがほしい・・・
2013-02-18 16:26:55 via web
pimpするやつじゃないけど、標準であるじゃん URL URL
2013-02-18 16:30:07 via web
というわけで、なんとなくたまに欲しくなっていた気もするけど、今までほぼ使ったことなかったPartialFunctionのcondOptについて使い方を説明してみます。
https://github.com/scala/scala/blob/v2.11.6/src/library/scala/PartialFunction.scala#L276-L286
使い道は、以下のようなパターン(play 2.1.0 のコードより)
https://github.com/playframework/Play20/blob/2.1.0/framework/src/play/src/main/scala/play/api/i18n/Messages.scala#L63-L73
code match { case SimpleLocale(language) => Some(Lang(language, "")) case CountryLocale(language, country) => Some(Lang(language, country)) case _ => None }
ポイントは
- match式を使っていて
- そのmatch式の戻り値の型がOption
- 先頭からmatchさせていったとき、一番最後以外のmatchした場合については、明示的にSomeに包んで返している
- なので最後は
case _ => None
というのがくる
つまりモチベーションとしては
- 毎回自ら明示的にSomeに包むの面倒
case _ => None
という定形コードうざい
でそれらをPartialFunction使って短く書けるものが、PartialFunctionのコンパニオンオブジェクトにcondOptという名前で標準で存在します。
さっきのをcondOptで書き換えると以下のようになります
PartialFunction.condOpt(code){ case SimpleLocale(language) => Lang(language, "") case CountryLocale(language, country) => Lang(language, country) }
はい、ただこれだけの違いです。ちなみに、パフォーマンス的にはAbstractPartialFunctionのオブジェクトのインスタンスなど*1が作られる分だけ、match式よりこっちのほうが微妙にオーバーヘッドがあります。(まぁこんな細かいパフォーマンスが問題になることは、ほぼないでしょうけれども)
*1: 内部でlift呼んでいるので、ほかにも作られるみたい https://github.com/scala/scala/blob/v2.10.1-RC1/src/library/scala/PartialFunction.scala#L214-L221