参照の値渡し
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2020/10/03 01:23 UTC 版)
参照の値渡し (共有呼び: call by sharing、オブジェクト呼び: call by object、call by object-sharing) は Barbara Liskov 他によって1974年にCLU言語で最初に call by sharing と呼ばれた評価戦略である。 日本語では参照の値渡しとも呼ばれる。Python、Iota、Java、Ruby、JavaScript、Scheme、OCaml、AppleScript等の多数の言語で使われている。しかしながら「参照の値渡し」という用語は一般的では無く、異なる情報源間で用語の混乱が見られる。例えば、Javaの分野ではJavaは全て値渡しであると言われている。参照の値渡しは、言語上の値がプリミティブ型ではなくオブジェクトに基づいているということ、つまり全ての値が「ボックス化」されていることを意味している。 参照の値渡しの意味論は参照渡しとは異なる: "In particular it is not call by value because mutations of arguments performed by the called routine will be visible to the caller. And it is not call by reference because access is not given to the variables of the caller, but merely to certain objects"(意訳「とりわけ、呼び出し先で行われた引数に対する変更は呼び出し元からも見えるため、値渡しではない。また、アクセスは呼び出し元の変数ではなく、単にあるオブジェクトに対して行われるため、参照渡しでもない。」) だから、例えば、変数が渡されたとき、呼び出し先のスコープ内で変数への代入を装うことは不可能である。ただし、関数は呼び出し元と同じオブジェクト(コピーされたものではない)にアクセスできるため、オブジェクトが可変(ミュータブル)であれば、関数内でのオブジェクトへの変更は呼び出し元にも反映される。これは値渡しの意味論とは異なる動作である。オブジェクトはコピーでもクローンでもない、つまり共有されているから、関数内での可変オブジェクトへの変更は、呼び出し元からも見えると言うことである。例として、配列(Array)が可変であるRubyで書くと: def f(arr) arr.append(1)endm = []f(m)p m これは [1] を出力する。なぜなら、appendメソッドは呼び出されたオブジェクトを変更しているからだ。 これらの言語では、変数を渡すことは、変数によって参照される実際のオブジェクト渡す(アクセスする)事を意味しており、オリジナルの(呼び出し元の)変数にアクセする事では意味しているわけでは無いため、関数内での代入は呼び出し元に影響を与えない。再束縛された変数(仮引数となる変数)は関数内にしか存在しないため、呼び出しと元の対応する変数(実引数となる変数)は元の束縛を維持する。上記のRubyでの変更の動作と新しいオブジェクトを引数に代入する次のコードを比較してみると: def f(arr) arr = [1]endm = []f(m)p m これは [] を出力する。なぜなら、arr = [1] という式は、新しい配列を、変数が参照する(つまりはオブジェクトの実体が保存されている)場所ではなく、変数そのものに再代入するからだ。 不変(イミュータブル)オブジェクトでは、オブジェクトの識別が変数そのものである言語を除き、参照の値渡しと値渡しに実質的な違いはない。可変オブジェクトでの参照の値渡しは、入出引数(input/output parameters)に代わるものである: 仮引数は代入せず(引数は上書きせず、オブジェクトの識別は変更しない)に、オブジェクト(引数)を変更する。 この用語は海外のPythonコミュニティ(call by sharingとして)および日本のRubyコミュニティ(参照の値渡しとして)では広く使用されているが、JavaやVisual Basic等の他の言語では同一の意味論でも値渡しとし、この場合の値はオブジェクトへの参照であると記述される場合が多い。
※この「参照の値渡し」の解説は、「評価戦略」の解説の一部です。
「参照の値渡し」を含む「評価戦略」の記事については、「評価戦略」の概要を参照ください。
参照の値渡し
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2022/02/20 07:25 UTC 版)
参照渡しで言うところの「参照」と呼ばれているものと、特定の言語で「参照」と呼ばれているものが必ずしも同じでない事には注意が必要。例えば、Javaは参照型を扱うための『Javaの「参照」』を持つが、これはPascal等のポインタ相当で、『参照渡しの「参照」』とは概念が違うため、『Javaの「参照」』を渡しても参照渡しであるとは言えない。C言語の「ポインタの値渡し」と同じである 。これは、Javaの参照型と似た参照型と、Javaのプリミティブ型に近い値型を持つC#を見ると理解しやすいだろう。C#では、特に指定しなければ参照型も値型も値渡しされるが、引数に ref もしくは out を使用する事によって参照渡しにする事ができる。『C#の値型』を渡すから値渡し、『C#の参照型』を渡すから参照渡しとはならない。
※この「参照の値渡し」の解説は、「引数」の解説の一部です。
「参照の値渡し」を含む「引数」の記事については、「引数」の概要を参照ください。
- 参照の値渡しのページへのリンク