モナドを中心としたパイプライン指向のプログラミング・スタイルを本ブログではモナディック・プログラミングと呼んでいます。
モナディック・プログラミングでは、モナドを使ったパイプラインが幹で、これを束ねてプログラムを構築していきます。
Try(4) 基本フォーム、Try(5) 基本フォーム2Try(6) 終了方法でTryモナドを使ったパイプラインを構築方法を整理しました。
終了方法として「Tryのまま返す」を選択した場合、該当するパイプラインは、より大きなパイプラインの部品として使用することができます。
準備
Tryモナドを返す関数としてTry(6) 終了方法で導入した以下のものを使います。
def f(a: Int, b: Int): Try[Int] = { def divAB = a / b def plus1(x: Int) = x + 1 def minus100DivB(x: Int) = Try(x / (b - 1)) Try(divAB).map(plus1).flatMap(minus100DivB) }
直列
関数fを直接に結線するパイプラインは以下になります。
def g(a: Int, b: Int) = { def f1(x: Int) = f(x, b) def f2(x: Int) = f(x, b - 1) def f3(x: Int) = f(x, b - 2) f1(a).flatMap(f2).flatMap(f3) }
正常系の実行結果は以下になります。
scala> g(1000, 4) res91: scala.util.Try[Int] = Success(8) scala> g(1000, 5) res92: scala.util.Try[Int] = Success(1)
異常系の実行結果は以下になります。
scala> g(1000, 0) res87: scala.util.Try[Int] = Failure(java.lang.ArithmeticException: / by zero) scala> g(1000, 1) res88: scala.util.Try[Int] = Failure(java.lang.ArithmeticException: / by zero) scala> g(1000, 2) res89: scala.util.Try[Int] = Failure(java.lang.ArithmeticException: / by zero) scala> g(1000, 3) res90: scala.util.Try[Int] = Failure(java.lang.ArithmeticException: / by zero)
並列
複数のパイプラインの結果を持ち寄って最終結果を計算する処理にはfor式を使うのが定番です。
def g(a: Int, b: Int) = { def f1(x: Int) = f(x, b) def f2(x: Int) = f(x, b - 1) def f3(x: Int) = f(x, b - 2) for { x <- f1(a) y <- f2(a) z <- f3(a) } yield x + y + z }
正常系の実行結果は以下になります。
scala> g(1000, 4) res97: scala.util.Try[Int] = Success(751) scala> g(1000, 5) res98: scala.util.Try[Int] = Success(300)
異常系の実行結果は以下になります。
scala> g(1000, 0) res93: scala.util.Try[Int] = Failure(java.lang.ArithmeticException: / by zero) scala> g(1000, 1) res94: scala.util.Try[Int] = Failure(java.lang.ArithmeticException: / by zero) scala> g(1000, 2) res95: scala.util.Try[Int] = Failure(java.lang.ArithmeticException: / by zero) scala> g(1000, 3) res96: scala.util.Try[Int] = Failure(java.lang.ArithmeticException: / by zero)
諸元
- Scala 2.10.0-M7
0 件のコメント:
コメントを投稿