1

私はscalaを学んでおり、次のコードに出くわしました。

def whileLoop(cond: => Boolean)(body: => Unit): Unit =
    if (cond) {
      body
      whileLoop(cond)(body)
    }
  var i = 10
  whileLoop (i > 0) {
    println(i)
    i -= 1
  }

出力は 10 対 1 の数字です。

したがって、cond と body はどちらも「名前による呼び出し」パラメーターです。つまり、関数で使用されたときに評価されます。私がそれを正しく理解していれば。私が理解していないのは、体がどのように

println(i)
i -= 1

適用される再帰の各レベルごとに変化し、変数 i が変化するにつれて本体が変化します。しかし、それはどのように正確に機能しますか?同じ関数本体が渡されるたびに、この関数は同じままですが、プログラムを実行すると、そうでないことがわかります。関数が毎回評価されることは知っていますが、内部の i 変数が毎回どのように変化するのか理解できないので、誰かがそれがどのように機能するか説明できますか?

4

3 に答える 3

1

=> Typeを指定してパラメーターを宣言すると、そのパラメーターを無名関数 (Type入力なしでそれのみを返す関数) として宣言することになります。そのため、関数が初めて呼び出されると、各パラメーターは毎回その特定の値に対して評価されますibody反復ごとに値が変更されるためi、プログラムは値が変更されるiたびに再評価bodyします。

複雑に聞こえるかもしれませんが、ご了承ください。を削除するとどうなるか見てみましょう=>

を削除すると、=>無名関数を再評価することを宣言していません。書き換えできないパラメータを定義しています。また、条件を毎回再評価することはできないため、無限のビュクレができます。

この説明が少しでもお役に立てば幸いです。

于 2015-05-28T21:54:17.777 に答える
1

この例では、ボディ

println(i)
i -= 1

本体の定義のスコープ内にある変数を操作するクロージャーです。iしたがってi、 は本体のローカル変数ではありません。つまり、操作は、メソッドの呼び出し後に破棄されるローカル コピーではなく、-=既存の値のみを変更します。i

同じことが条件にも当てはまります。これは同じ variable をキャプチャするクロージャーであるiため、本体を実行するたびに、条件は の現在更新された値を確認しますi

意味を変えずに例を少し書き直してみましょう: まず、whileLoop名前による呼び出しパラメータの代わりに引数として関数を取るように書き直すことができます:

def whileLoop(cond: () => Boolean)(body: () => Unit): Unit =
  if (cond()) {
    body()
    whileLoop(cond)(body)
  }

これwhileLoopは、名前による呼び出し引数が式の評価ではなく式として渡されるため、意味的には同じです。免責事項: パフォーマンスなど、技術的な違いがあるかどうかはわかりません。

次に、渡される式と引数を取らない関数を作成condできbodyます。

val condDef = () => i > 0

val bodyDef = () => {
  println(i)
  i -= 1
}

iどちらもパラメーターの一部でもなく、本体内で定義されていない変数を参照するためi、スコープに入れる必要があります。

def main(args: Array[String]) {
  var i = 10

  val condDef = () => i > 0

  val bodyDef = () => {
    println(i)
    i -= 1
  }

  whileLoop (condDef) {
    bodyDef
  }
}

Soiは両方からアクセスでき、condDefandbodyDefは評価時にアクセスおよび変更されます。

于 2015-05-28T21:54:19.357 に答える
1

i -= 1 は、変数 i を取り、それを 1 だけ減分された値に再割り当てします。ボディは、ボディが呼び出されるたびに変更される同じ i 変数を参照しています。すべての再帰と whileLoop を本質的に無視すると、次のようになります。

var i = 10
println(i) // prints 10
i -= 1
println(i) // prints 9
i -= 1
...
i -= 1
println(i) // prints 1
i -= 1
println(i) // prints 0
于 2015-05-28T21:54:29.637 に答える