2012年4月17日火曜日

Scala Tips / Validation (2) - 関数で値の取り出し

Validationから値を取り出すイディオムです。

前回は、Validationに格納されている成功(Success)の値を取り出すイディオムでした。失敗(Failure)の場合はデフォルト値を使いました。

今回は、Validationに格納されている成功(Success)と失敗(Failure)を同じ型の値に変換して取り出すイディオムです。

Validation[Throwable, Int]に対して、Successの場合はSuccessの値(Int)をStringに、Failureの場合はFailureの値ThrowableをStringにして返す処理を考えます。SuccessのIntをStringに、FailureのThrowableをStringに変換する関数は外部から与えることにします。

(分類の基準)

Java風

if式でValidation#isSuccessメソッドを使ってSuccessとFailureの判定をして、処理を切り分ける事ができます。SuccessとFailureの値を取り出し、適切な関数を適用します。SuccessとFailureのいずれもasInstanceOfが必要になるので、あまり使いたくない用法です。

def f(a: Validation[Throwable, Int], g: Throwable => String, h: Int => String): String = {
  if (a.isSuccess) {
    h(a.asInstanceOf[Success[Throwable, Int]].a)
  } else {
    g(a.asInstanceOf[Failure[Throwable, Int]].e)
  }
}

Scala風

match式を使うとSuccessとFailureのパターンマッチングで書くことができます。

def f(a: Validation[Throwable, Int], g: Throwable => String, h: Int => String): String = {
  a match {
    case Success(s) => h(s)
    case Failure(e) => g(e)
  }
}

Scala

ValidationはScalazの機能なので、「Scala」というのは変ですが、foldメソッドを用いるのがScala流のコーディングです。Validationのfoldメソッドは、第一引数にFailureの値を変換する関数、第二引数にSuccessの値を変換する関数を指定します。

def f(a: Validation[Throwable, Int], g: Throwable => String, h: Int => String): String = {
  a.fold(g, h)
}

Scalaz

foldメソッドを使う方式は「Scala」のところで紹介しました。その他に、Scalazらしい特徴的な方式はないと思います。

ノート

取り出す値の型がSuccessの値の型が同じ場合には、「|||」メソッドを使うことができます。

Validationの「|||」メソッドは、Successの場合は値の取り出し、Failureの場合は指定したFailureの値を関数で変換して取り出す関数です。

def f(a: Validation[Throwable, Int], g: Throwable => Int): Int = {
  a ||| g
}

また、foldメソッドも第二引数(Successの場合に適用する関数)を省略して、以下のような使い方ができます。

def f(a: Validation[Throwable, Int], g: Throwable => Int): Int = {
  a.fold(g)
}

諸元

  • Scala 2.9.2
  • Scalaz 6.0.4

0 件のコメント:

コメントを投稿