11

私が理解している限り、Scala では無名関数に複数のリターン ポイントを設定する方法はありません。つまり、

someList.map((i) => {
    if (i%2 == 0) return i // the early return allows me to avoid the else clause
    doMoreStuffAndReturnSomething(i) // thing of this being a few more ifs and returns
})

を発生させerror: return outside method definitionます。(そして、それを上げなければ、コードは私が望んでいるように機能しません。)

私ができる1つの回避策は次のとおりです

someList.map({
    def f(i: Int):Int = {
        if (i%2 == 0) return i
        doMoreStuffAndReturnSomething(i)
    }
    f
})

ただし、これを行う別の「受け入れられた」方法があるかどうかを知りたいです。内部関数の名前なしで行く可能性はありますか?

continue(使用例は、ループ内で値を持つ構造をエミュレートすることです。)

編集

doMoreStuffその部分は実際には次のようになる可能性があるため、elseステートメントを回避する必要があることを信じてください。

val j = someCalculation(i)
if (j == 0) return 8
val k = needForRecalculation(i)
if (k == j) return 9
finalRecalc(i)
...

–<code>else 構造しかif利用できない場合、これは簡単にめちゃくちゃになります。

もちろん、最初に示した単純な例では、 を使用するだけの方が簡単ですelse。申し訳ありませんが、これは明らかだと思いました。

4

4 に答える 4

6

匿名関数がそれほど複雑な場合は、より明示的にします。無名関数は、数行以上の複雑なものには適していません。using メソッド内で宣言することにより、メソッドをプライベートにすることができます

def myF(i:Int):Int = {
    if (i%2 == 0) return i
    doMoreStuffAndReturnSomething(i)
}
someList.map(myF(_))

これは回避策のバリエーションですが、よりクリーンです。どちらも、ローカル メソッド スコープに対して非公開にしています。

于 2010-05-24T17:41:19.637 に答える
3

あなたが与えた例は、if ステートメントで簡単に解決できます。これを行うことによるパフォーマンスやその他のペナルティはありません。

しかし、大まかに次のような他の状況が発生する可能性があります

if (test) {
  if (anotherTest) {
    val a = someComputation()
    if (testOf(a)) return otherComputation()
  }
  else if (yetAnotherTest) return whatever()
}
bigComputation()

if ステートメントのもつれやコードの重複を避けたい場合は、このような状況に対処する方法がいくつかあります。

必要な計算だけを行うために、 ( と を使用して) を使用したり、状態の流れを維持しOptionたりするために、さまざまな卑劣なことができます。EitherorElsefold

あなたが提案するように、defを作成する方が本当に良いです。ただし、比較のために、オプションのラッピング スタイルを考えてみましょう。

i => {
  ( if ((i%2)==0) Some(i) 
    else None
  ).getOrElse(doStuffAndReturn(i))
}

上記の大きな例では、このスタイルは次のようになります。

( if (test) {
    if (anotherTest) {
      val a = someComputation()
      if (testOf(a)) Some(otherComputation()) else None
    }
    else if (yetAnotherTest) Some(whatever())
    else None
}).getOrElse(bigComputation())

個人的には、それがより明確であるとは思いません (そして確かに高速ではありません) が、それは可能です。

于 2010-05-24T18:28:37.563 に答える
3

コードのコメントでは、キーワードを避けたいと書いていますelseが、私見では、これはまさにあなたが望むことであり、さらに2文字短くなります;-)

someList.map((i) => {
    if (i%2 == 0) i else
    doMoreStuffAndReturnSomething(i)
})
于 2010-05-24T17:43:36.487 に答える
1

無名関数の戻り点に関する主な問題は、通常は予期しない場所で無名関数が発生する可能性があることだと思います。そのため、return ステートメントが実際にどのクロージャーに属しているかは明確ではありません。この問題は、def—<code>return* 対応を明示的に要求することで解決されます。

あるいは、戻り元のステートメントの周りにガードが必要になります。breakable—<code>break しますが、残念ながらそれで値を返すことはできません。いくつかの継続ベースのソリューションはその目標を達成することができますが、一般的な受け入れとそこでのライブラリを待ちたいと思います.

于 2010-08-13T18:29:45.567 に答える