Play2.1内部に、独自の Functor URL とか Applicative URL とか Monoid URL が追加されていて味わい深いですね・・・
2012-11-18 01:16:51 via web
というわけで、Play2.1から独自のFunctorとかApplicativeとかAlternative(ApplicativePlus)があるので簡単にOptionのApplicativeの使い方だけ紹介。
https://github.com/playframework/Play20/blob/2.1.0/framework/src/play/src/main/scala/play/api/libs/functional/Util.scala
Scalazでその辺り知ってる人は、簡単に理解できるはずです。ところで、なぜかMonadのtypeclassはないんですね・・・。
ちょっと引用
http://qiita.com/items/b25b14284883ee1549e7
def notification = Action(parse.json){ request => val optText = request.body.\("text").asOpt[String] val optId = request.body.\("id").asOpt[String] val optUser = request.body.\("user").asOpt[String] val tweet = for(text <- optText; id <- optId; user <- optUser) yield new Tweet(text,id,user) }スゴイ!Optionスゴイよ!!(あと、forとかyieldも)
はい、Option便利ですけど、このパターンMonadじゃないのでfor式必要ないですねApplicative(もっと正確にはApply)ですね。つまりこの前書いたこれ
Scalacheck の Arbitrary.scala を scalaz の Applicative を使って書き換えてみる
と(構文がちょっとだけ違うだけで)ほぼ全く同じことが、Scalazを使わずに、Play2.1の中にあるfunctionalのものでできます。以下のようになります
import play.api.libs.functional.syntax._ def notification = Action(parse.json){ request => (request.body.\("text").asOpt[String] ~ request.body.\("id").asOpt[String] ~ request.body.\("user").asOpt[String] )(Tweet) }
わー、変数がいっぱい消えて、さらに短く書けましたね。Scalaz分かる人にむけて簡単に説明しておくと、~というのがApplicativeBuilderの|@|に相当するものです。記号が嫌いな人向けに~ではなくandという別名もあるみたいです。
CanBuild1からCanBuild21が、ApplicativeBuilderですかね。*1その他tupledとか、ある程度Scalazと同じメソッドありそうです。
(scalazと比べた場合に)細かいところの使い勝手でツッコミどころは大量にありそうですが、まぁこの程度のOptionのApplicativeは(Scalazの依存を加えずに)手軽に使えるので、使ってみればいいんじゃないでしょうかね。
*2
追記:
今回のやつは、「とりあえず使えるようになってるから試しに使ってみた」という感じですが、「そもそもPlayにおいて、普通にやるならバリデーション使えばよい(?)」とか「functionalはどちらかというと内部実装のためにあるもので、あまりユーザーが直接使うことを意図していないかもしれない(?)」ので(以下のtogetter参照)
Play2.1のfunctionalパッケージとバリデーション
そのあたりは自己責任というか、適切な方法を調べましょう(というか、教えてください(´・ω・`) )