コミケ告知

サークル活動の詳細は circle タグの記事へ。
2015年9月13日日曜日

tryする末尾再帰関数が普通には書けないScala

TL;DR

try~catch内で値を返す再帰関数を書くには、scala.util.Tryを使う。

説明


Scalaでは末尾再帰関数は最適化してくれるし、それをtailrecアノテーションでチェックすることができます。(最適化が効かない場合にコンパイルエラーが出るようになる)
@scala.annotation.tailrec
def f(n: Int): Int = {
  ...  // (略)
  f(n - 1)
}
ただこれ、try~catchを付けて、そこで値を返そうとするとうまくいかないんですよね~
@scala.annotation.tailrec
def f(n: Int): Int = {
  try {
    ...  // (略)
    f(n - 1)
  } catch {
    // どの場合も返す型は正しいものとする
  }
}
scalac Main.scala
Main.scala:3: error: could not optimize @tailrec annotated method f: it contains a recursive call not in tail position
  def f(n: Int): Int = {
エラーメッセージも正しくなくてなんだこりゃって感じですが、stackoverflowに回答がありました。

何度も回答がEditされていますが、その一番下。try~catch節ではなく、scala.util.tryを用いることで回避できるようです。
@scala.annotation.tailrec
def f(n: Int): Int = {
  scala.util.Try(例外の出る処理内容) {
    case Success(処理の返り値) => ...
    case Failure(e: 例外の型) =>
    case Failure(e: 例外の型) =>
  }
}

知っていて最初からこれで書けば面倒くさいことはないんだけど…Scala、あちこち珍妙なとこあるよな。

0 件のコメント:

コメントを投稿