Boxについて調べてみた

Boxはオブジェクトのコンテナの一つで、要するにscala.Optionっぽいもの。Liftアプリケーションでは頻出なので、調べてみた。

Box.apply

Boxインスタンスを作るファクトリ。 Box(someValue) *1で、boxな何かが返ってくる。

  • 任意のオブジェクトで:オブジェクトが値を持つならFull(value)、オブジェクトがnullならEmpty
  • リストで:値があるならFull(リスト)、Nil(空リスト)ならEmpty
  • Optionで:Some(value)ならFull(value)、NoneならEmpty
  • Boxを食わせて:Full(value)なら新たなFull(value)、Full(null)かEmptyならEmpty
  • 部分関数と値を食わせて:部分関数に値を適用できるならその結果、できないならEmpty

インスタンスの扱い

中身を取り出すときは、 box.openOr(default) 。Fullなら中身が、Emptyなら指定したdefault値を返す。open_!メソットはシンプルだが、インスタンスがEmptyだった場合にNullPointerExceptionを投げるので、多用すべきではない。Optionのgetと同等。

Emptyを避けたいなら、 box.or(alternative) 。Emptyなら指定したalternativeが返されるので、初期値設定っぽいことができる。

中身の操作は box.map で行う。Emptyの場合はそのままEmptyになるので、渡す関数内部でnullチェックが不要になる。

Box に対してFullかEmptyか判断するマッチングは必須ではなく、処理の流れを変える必要のない場面では、openOrで取り出せばいい。外部に出力する段階で1度だけopenOrするのが理想的で、orや部分関数の適用とかを使っていくと恐らく綺麗にかけるんだろうと思うが、あまりこだわり過ぎる部分ではなさそう。

Optionとの違い

Optionとの違いは、Box.applyが豊富であることで、それ以外はそれほど違わないように見える。

たとえば、キーを指定するなどでデータベースから明らかに1件だけselectする場面で、

Box(SomeMetaMapper.findAll(By(SomeMetamapper.id, someId)))

とできるのが、便利。

この辺のエラーチェック関係はいろんなやり方があると思うけど、Boxでラップして使うのが、もっとも敷居が低くかつ無難だと思う。

*1:Scalaではapplyメソッドはカッコで呼ぶことができる。シンタックスシュガー。