1

たとえば、このコードサンプルのように、無名関数を引数として渡すと:

val someMap = someData.map(line => (line.split("\\|")(0), // key 
                                    line.split("\\|")(1) + "|" + // value as string concat
                                    line.split("\\|")(4) + "|" +
                                    line.split("\\|")(9)))

たとえば、次のような ArrayIndexOutOfBoundsException をキャッチできます。

try {
    val someMap = someData.map(line => (line.split("\\|")(0), // key 
                                        line.split("\\|")(1) + "|" + // value as string concat
                                        line.split("\\|")(4) + "|" +
                                        line.split("\\|")(9)))
} catch {
    case e1: ArrayIndexOutOfBoundsException => println("exception in line " )
}

これの問題は、内部関数のスコープにアクセスできないことです。lineこの場合、例外の原因となった (無名関数から) を出力したいと思います。

これどうやってするの?無名関数内で例外をキャッチする方法はありますか? デバッグ目的で匿名関数のスコープに外部からアクセスする方法はありますか?

編集: Scala 2.9.3を使用しています

4

4 に答える 4

3

他の回答は、Eitherなどを使用した優れた機能的ソリューションを提供します.Scala 2.10を使用している場合は、次のように使用することもできTryます

val lines = List("abc", "ef");
println(lines.map(line => Try(line(3))));

List[Try[Char]]各要素が成功したか失敗したかを調べることができます。(私はこれをコンパイルしようとはしていません。)


なんらかの理由で例外が必要な場合は、マッピング関数内で例外をキャッチし、行に関する情報とともに再スローする必要があります。例えば:

// Your own exception class holding a line that failed: 
case class LineException(line: String, nested: Exception)
  extends Exception(nested);

// Computes something on a line and throw a proper `LineException`
// if the processing fails:
def lineWorker[A](worker: String => A)(line: String): A =
  try {
    worker(line)
  } catch {
    case (e: Exception) => throw LineException(line, e);
  }

def getNth(lines: List[String], i: Int): List[Char]
  = lines.map(lineWorker(_.apply(i)));

val lines = List("abc", "ef");
println(getNth(lines, 1));
println(getNth(lines, 2));

Catchfromを使用して表現することもできますscala.util.control.Exception

case class LineException(line: String, nested: Throwable)
  extends Exception(nested); // we need Throwable here ^^

import scala.util.control.Exception._

// Returns a `Catch` that wraps any exception to a proper `LineException`.
def lineExceptionCatch[T](line: String): Catch[T]
  = handling[T](classOf[Exception]).by(e => throw LineException(line, e));

def lineWorker[A](worker: String => A)(line: String): A =
  lineExceptionCatch[A](line)(worker(line))

// ...
于 2013-06-19T08:37:45.607 に答える
3

おそらくこれはあなたにいくつかのアイデアを与えるでしょう:

try {
    val someMap = someData.map { line =>
            try {
                (line.split("\\|")(0), // key 
                 line.split("\\|")(1) + "|" + // value as string concat
                 line.split("\\|")(4) + "|" +
                 line.split("\\|")(9)))
            } catch {
                case inner: ArrayIndexOutOfBoundsException => {
                        println("exception in " + line)
                        throw inner;
                    }
            }
        }
} catch {
    case outer: ArrayIndexOutOfBoundsException => ...
}
于 2013-06-19T06:53:58.187 に答える
2

まず、外側の try/catch は役に立ちません。List (または他の構造) が空の場合、map関数は何も実行しません => noArrayIndexOutOfBoundsExceptionがスローされます。

内側のループについては、Scalaz を使用した別のソリューションを提案します。

import scalaz._
import EitherT._
import Id.Id

val someMap = someData.map { line =>
  fromTryCatch[Id, (String, String)] {
    (line.split("\\|")(0), // key
       line.split("\\|")(1) + "|" + // value as string concat
       line.split("\\|")(4) + "|" +
       line.split("\\|")(9))
  }
}

次に、 List[EitherT[...]] で操作を連鎖させます

于 2013-06-19T07:17:14.930 に答える