10

私の同僚と私は、次のコードの動作に少し困惑しています。

def a: String = {
  None.foreach(return "1")
  return "2"
}

def b: String = {
  None.foreach(x => return "1")
  return "2"
}

予想どおり、呼び出すbと「2」が返されます。ただし、呼び出すaと「1」が返されます。いつ実行されるのか正確return "1"に評価されているのはいつですか?a

4

5 に答える 5

11

フォームのすべての*関数評価

f({code})

と同等です

val temp = { code }
f(temp)

したがって、最初のケースでは、

val temp = return "1"
None.foreach(temp)   // Never reach this point!

第二に、

val temp = (x: Nothing) => return 1
  // Equivalent: new Function1[Nothing,String]{ def apply(x: Nothing) = return "1" }
None.foreach(temp)   // Never call that weird function!

だからすべてが大丈夫です。

しかし、待って、foreachかかりますA => Unitreturn "1"そのような機能はどうですか?さて、Scalaは可能な限り最も具体的なタイプから始めます(Nothingこれはあらゆるもののサブクラスであり、したがって、存在できないことを除いて、あなたが求めることは何でもすることを約束します)。そして、ステートメントによって値が生成されないため(制御はリターンを介してエスケープされます)、から変更されることはありませんNothing。したがって、実際にNothingは、のサブクラスですFunction1[A,Unit]

そして、それを生成するためにNothing(まあ、それを生成するふりをするために)、実際にコードを実行して戻ります。

実際、パラメータを名前で渡すと、密かに変換されて() => { Code }評価なしで渡されます。

于 2012-11-30T21:22:32.447 に答える
2

他の人はその振る舞いを説明しましたが、まったく使用しないのが最善returnです。

私は次のようなものを書きます。

def b: String = {
  None.map(x => "1").getOrElse("2")
}

または、それが私である場合、何かに一致する最初のアイテムを返したい場合にList使用します。collectFirst

編集:質問がとしてタグ付けされているのがわかりますfunctional programmingreturn機能的なスタイルでプログラムしようとする場合は避けてください。A => Bのマップを作成します。使用する場合はreturn、その型署名を無効にします。

def a: String = { 
  val a = Option(5).map(x => if(x==6) return "aa" else 6); // isnt returning a `B` when x == 5.
  a.toString
};
于 2012-11-30T21:23:12.423 に答える
1

それは本当にクールです-私はそれを知りませんでした。言語リファレンスを見ると、http: //www.scala-lang.org/docu/files/ScalaReference.pdfの91ページにあります。

return式returneは、名前付きメソッドまたは関数を囲むいくつかの本体の内部で発生する必要があります。ソースプログラムの最も内側にある名前付きメソッドまたは関数fは、明示的に宣言された結果タイプを持っている必要があり、eのタイプは それに準拠している必要があります。戻り式は式eを評価し、 fの結果としてその値を返します。

..。

applyコンパイラによって無名関数の拡張として生成されたメソッドは、ソースプログラムでは名前付き関数としてカウントされないため、戻り式のターゲットになることはありません。

ネストされた無名関数からの戻りは、をスローしてキャッチすることで実装されscala.runtime.NonLocalReturnExceptionます。リターンポイントとそれを囲むメソッドの間に例外がキャッチされると、例外が発生する可能性があります。キーの比較により、これらの例外は、リターンによって終了するメソッドインスタンスによってのみキャッチされることが確認されます。

戻り式自体が無名関数の一部である場合、戻り式が実行される前に、 fの囲んでいるインスタンスがすでに戻っている可能性があります。その場合、スローscala.runtime.NonLocalReturnExceptionされたものはキャッチされず、コールスタックに伝播します

于 2012-11-30T21:17:05.460 に答える
1

aでは、foreachは行に到達するreturn "1"前に実行されreturn "2"ます。foreach内にある場合でも、コードは実行されるため、1が返されます。bでは、xは「自己型アノテーション」(http://www.scala-lang.org/node/124)を介して操作に割り当てられています。のreturn "1"

Scalaの継承に関するこの投稿は役に立つかもしれません:このキーワードを使って継承しますか?

共有してお楽しみください

于 2012-11-30T21:17:12.853 に答える
1

Scalaは、熱心なアプリケーションオーダー評価を使用します。これは、引数が関数のパラメーターに置き換えられる前に評価されることを意味します。また、関数がそれ自体に評価されることを思い出してください。関数の戻り値を評価するのは関数適用です。次に、これらの各引数が何に評価されるかを見てみましょう。

scala> :t () => "1"
() => java.lang.String

したがって、2番目のケースでは、関数を取得します。渡される前に(それ自体に対して)評価されますがNone、要素がないため、適用されることはありません。ただし、return "1"適用する必要はありません。評価する必要があるだけです。これには、制御をリダイレクトし、それを含む関数から「1」を返すという副作用があります。

于 2012-11-30T22:15:30.997 に答える