2

私はおもちゃの言語でこのコード行を持っています。print-function は引数のリストを取り、それらを出力します。

print(a, (a := 5, a))

値による呼び出しまたは名前による呼び出しを使用した場合、出力に違いはありますか? もしそうなら、アウトプットはどうなるでしょう。

aに初期化されていると考えられ0ます。

4

1 に答える 1

4

「call-by-value」の場合、引数は通常(ほとんどの言語で) 左から右に評価されるため、式は次のようになります。

arg1 := a // copy value of a to arg1
a := 5 // copy 5 to a
arg2 := a // copy value of a to arg2
print(arg1, arg2) // print(0, 5)

「名前による呼び出し」は明らかに、次のようなものを生成する遅延評価の形式です。

arg1 := function() {return a;}
arg2 := function() {a := 5; return a;}
print(arg1, arg2)

したがって、この場合、結果は次の 2 つの要素に依存します。

  • この言語では、クロージャーが参照または値によって変数をキャプチャするかどうか。値によるキャプチャの場合、最初のクロージャがキャプチャしa := 5た値には影響しません。aただし、ローカル変数の再割り当てを許可するほとんどの言語は、参照によるキャプチャを実装しています (JavaScript など)。
  • print関数がその引数を評価することを決定する順序は、それがどのように記述されているかによって異なります。

クロージャーが値によってキャプチャする場合、代入は 2 番目のクロージャーの のコピーにのみ影響するため、print(…)は yieldになります。0 5a := 5a

クロージャが参照によってキャプチャする場合、出力がどうなるかを推測することしかできません。printしかし、関数が次のようなことをする可能性はかなり高いです:

print := function(lazy x, lazy y) {
    writeToOutput(x())
    writeToOutput(y())
}

どちらの場合でも、結果は同じ ( 0 5) になります。これx()は、 が最初に評価され、結果y()が処理されてから評価されるためです。この場合、 の値はa関数が で終了するまで変化しませんx

しかし、これは推測にすぎません。printそれらを任意の順序で (および任意の回数) 評価できます。

于 2016-09-09T13:29:02.423 に答える