私はおもちゃの言語でこのコード行を持っています。print
-function は引数のリストを取り、それらを出力します。
print(a, (a := 5, a))
値による呼び出しまたは名前による呼び出しを使用した場合、出力に違いはありますか? もしそうなら、アウトプットはどうなるでしょう。
a
に初期化されていると考えられ0
ます。
私はおもちゃの言語でこのコード行を持っています。print
-function は引数のリストを取り、それらを出力します。
print(a, (a := 5, a))
値による呼び出しまたは名前による呼び出しを使用した場合、出力に違いはありますか? もしそうなら、アウトプットはどうなるでしょう。
a
に初期化されていると考えられ0
ます。
「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 5
a := 5
a
クロージャが参照によってキャプチャする場合、出力がどうなるかを推測することしかできません。print
しかし、関数が次のようなことをする可能性はかなり高いです:
print := function(lazy x, lazy y) {
writeToOutput(x())
writeToOutput(y())
}
どちらの場合でも、結果は同じ ( 0 5
) になります。これx()
は、 が最初に評価され、結果y()
が処理されてから評価されるためです。この場合、 の値はa
関数が で終了するまで変化しませんx
。
しかし、これは推測にすぎません。print
それらを任意の順序で (および任意の回数) 評価できます。