0

条件のネストされたブロック、for ループ、およびタプルを返すための try/catch ブロックがあります。

  val (a, b) = {
    if (...) {
      for (...) {
        try {
          getTuple(conf)
        } catch {
          case e: Throwable => println(...)
        }
      }
      sys.exit
    } else {
      try {
        getTuple(userConf)
      } catch {
        case e: Throwable => println(...); sys.exit
      }
    }
  }

条件が一致する場合は、ifx 種類の構成を試してみたいと思いconfます。getTuple例外がスローされたら、次のものを試します。が例外をスローしない場合getTupleは、タプルに結果を入力します。getTupleタプルを返します(a,b)

問題: ただし、 が例外をスローしない場合、forループは終了しgetTupleません。私も試しましたが、ループbreakを終了するだけでなく、タプルを返す必要があるため、機能しません。for

どうすればこれを機能させることができますか?

4

5 に答える 5

3

ループや例外を処理する代わりに、Scala のより機能的な機能を使用することをお勧めします。

一部の入力で例外をスローする関数があるとします。

def myfn(x: Double): Double =
  if (x < 0)
    throw new Exception;
  else
    Math.sqrt(x);

返すようにリファクタリングすることもできますOption:

def optMyfn(x: Double): Option[Double] =
  if (x < 0)
    None;
  else
    Some(Math.sqrt(x));

または、元のコードを変更したくない (または元のコードを変更できない) 場合は、次のように単純にラップできますException.Catcher

def optMyfn(x: Double): Option[Double]
  = scala.util.control.Exception.allCatch.opt(myfn(x));

それでは、一連の数字を見てみましょう。関数が成功する最初の数字を見つけたいと思います。

val testseq: Seq[Double] = Seq(-3.0, -2.0, 2.0, 4.0, 5.0);

Scala の関数型機能を使用して関数をすべての要素に適用し、最初のSome結果を次のように見つけることができます。

testseq.toStream.map(optMyfn _).flatten.headOption

を使用しなくても同様に機能しますが、最初の成功した結果を見つけるために必要な要素だけでなく、すべての要素に対して不必要にtoStream呼び出すことになります。ストリームは計算を遅延させます。optMyfn

(別のオプションは、のようにビューを使用することです

testseq.view.map(optMyfn _).collectFirst({ case Some(x) => x })

.)

于 2013-02-26T11:49:08.867 に答える
3

例外をスローする代わりに、getTuple は として評価する必要Option[Tuple2[T,U]]があります。より意味があり、プログラムの流れを中断しません。

このようにして、次のような for を持つことができます。

val tuples: List[Option[Tuple2[T,U]] = for {
  c <- configs
} yield getTuple(c)

val firstWorkingConfig: Option[Tuples2[T,U]] = tuples.flatten.headOption

// Exit the program if no config is okay
firstWorkingConfig.getOrElse {
  sys.exit
}

お役に立てれば

于 2013-02-26T10:26:27.043 に答える
1

作業タプルを取得するまでループしたい場合は、whileループの方が理にかなっています。for ループのセマンティクスは、反復するすべての要素の本体を評価することです。あなたの目標は、条件を満たした最初の後に停止することなので、while ループの方がはるかに自然に見えます。もちろん、より機能的な代替手段がいくつかあります。たとえば、次のようになります。

  • 例外に対応するgetTupleでラップします。OptionNone
  • 呼び出しをgetTuple反復可能/トラバース可能なコレクションに入れる
  • そうでない最初の要素を取得するNone

私がコンセプトを説明しているときに、Romain Sertelonがアイデアの良い例を挙げてくれました...

于 2013-02-26T10:20:40.610 に答える
1

sys.exit呼び出しは、ステートメントでちょっと間違っていますifcatchtry が成功した場合に tupe を返すことができるように、句内にある必要があります。

于 2013-02-26T10:12:40.437 に答える
0

別の解決策は、ブロック全体をメソッドにラップし、次のように return を使用することです。

  val (a: Type, b: Type) = setup(...)

  def setup(...) : (Type, Type) = {
    if (...) {
      for (...) {
        try {
          return getTuple(...)
        } catch {
          ...
        }
      }
      sys.exit
    } else {
      try {
        return getTuple(...)
      } catch {
        case e: Throwable => println(...); sys.exit
      }
    }
  }

Scala の基本をもっと学ぶべきだと思いますが、今のところはうまくいっています。

回答ありがとうございます。

于 2013-02-26T11:58:49.957 に答える