回答編集履歴
2
最終稿
test
CHANGED
@@ -62,6 +62,16 @@
|
|
62
62
|
|
63
63
|
|
64
64
|
|
65
|
+
### Javaの引数渡しの思考実験 (2019-05-02)
|
66
|
+
|
67
|
+
Javaで、1979年の議論を実現するには次のようにする。荒唐無稽ですが。
|
68
|
+
|
69
|
+
- Call by Value オブジェクトをシリアライズして渡す。呼び元のオブジェクトには全く影響を及ぼさない(mutableのみ)ただし高オーバーヘッド。
|
70
|
+
|
71
|
+
- call by reference 仮引数をfinal宣言して破壊的代入を許さなくする。あるいは、(できるなら)メソッド呼び出しをネストしたブロックにインライン展開、内部ブロックから実引数を直接参照する。できない場合が多い。
|
72
|
+
|
73
|
+
|
74
|
+
|
65
75
|
### CLU (2019-05-02)
|
66
76
|
|
67
77
|
|
@@ -124,7 +134,7 @@
|
|
124
134
|
|
125
135
|
- スタック上の複数の変数がヒープ上のオブジェクトを共有する。
|
126
136
|
|
127
|
-
- cluster の private 変数によって、ヒープ上の複数のオブジェクトが別のオブジェクトを共有する。再帰的な共有
|
137
|
+
- cluster の private 変数によって、ヒープ上の複数のオブジェクトが別のオブジェクトを共有する。再帰的な自己共有や、循環的な自己共有も可能。
|
128
138
|
|
129
139
|
- 関数呼び出しによって、呼び元の実引数と呼び先の仮引数が、ヒープ上のオブジェクトを共有する。
|
130
140
|
|
@@ -134,40 +144,104 @@
|
|
134
144
|
|
135
145
|
|
136
146
|
|
137
|
-
**call
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
o
|
147
|
+
**call by sharing 共有の何が新しいと思ったのか 1979**
|
148
|
+
|
149
|
+
|
150
|
+
|
151
|
+
代入とは
|
152
|
+
|
153
|
+
- オブジェクトの本体はコピーされない
|
154
|
+
|
155
|
+
- 代入はオブジェクトの状態に影響を与えない
|
156
|
+
|
157
|
+
- 代入後、オブジェクトは変数によって共有される
|
158
|
+
|
159
|
+
|
160
|
+
|
161
|
+
引数渡しとは
|
162
|
+
|
163
|
+
- 仮引数は呼び先のルーチンのローカル変数とみなす
|
164
|
+
|
165
|
+
- 実引数の式が評価され評価結果のオブジェクトが仮引数に代入される(ローカル変数の初期化)
|
166
|
+
|
167
|
+
- この手法は、伝統的な引数渡しのなかに該当するものがほとんど見当たらない(LISPの引渡しに似ている)
|
168
|
+
|
169
|
+
|
170
|
+
|
171
|
+
伝統的な引数渡しとの相違点
|
172
|
+
|
173
|
+
- call by value オブジェクトの本体を変更したら、呼び元にも変更が見える(mutableな場合)
|
174
|
+
|
175
|
+
- call by reference 呼び元の変数のエイリアスではない。オブジェクトの本体を指している
|
176
|
+
|
177
|
+
|
178
|
+
|
179
|
+
したがって、call by sharing と呼ぶことにする。
|
180
|
+
|
181
|
+
|
182
|
+
|
183
|
+
Barbara Liskov et al., 'CLU Reference Manual', MIT Laboratory for Computer Science, Cambridge, MA, 1979
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
設計にかかわる議論は78項目にわたって記述されている。それらは未読。
|
188
|
+
|
189
|
+
Programming Methodology Group, CLU Design Notes, MIT Laboratory for Computer Science, Cambridge, MA, 1973-1979.
|
190
|
+
|
191
|
+
|
192
|
+
|
193
|
+
手元の記事には実装の詳細が一部だけ掲載されている。拾い読み程度。読まないかもしれない。
|
194
|
+
|
195
|
+
B. Liskov, A. Snyder, R. Atkinson et al., 'Abstraction Machanisms in CLU', CACM vol. 20 no. 8, 1977
|
196
|
+
|
197
|
+
オブジェトディスクリプタの解説では定数はスタックに置かれるようだ。その他はヒープに置く。
|
198
|
+
|
199
|
+
|
200
|
+
|
201
|
+
**by objectという用語 1992 **
|
202
|
+
|
203
|
+
1992年にリスコフは call-by-sharing という用語を使っていない。call-by-object は記述がなく、"by object"が登場するのは、変数共有を排除することで推論が容易になるというところだけ。
|
204
|
+
|
205
|
+
|
206
|
+
|
207
|
+
> In fact, CLU procedures do not share variables at all. In addition to there being no free variables, there is no call-by-reference. Instead arguments are passed "by object"; the (pointer to the) object resulting from evaluating the actual argument expression is assigned to the formal. (Thus passing a parameter is just doing an assignment to the formal.) Similarly, a pointer to a result object is returned to the caller. We have found that ruling out shared variables seems to make it easier to reason about programs.
|
208
|
+
|
209
|
+
|
210
|
+
|
211
|
+
Barbara Liskov, 'A History of CLU', MIT Laboratory for Computer Science, Cambridge, MA, 1992
|
212
|
+
|
213
|
+
|
214
|
+
|
215
|
+
free variables は LISP の用語で(束縛されない)自由変数と訳せる。ここではグローバル変数のこと。
|
216
|
+
|
217
|
+
"by object" は、call-by-reference を指すとも、オブジェクトの本体を渡すともとれる。
|
218
|
+
|
219
|
+
object resulting from evaluating the actual argument expression は、正格処理として実引数の式を評価して結果オブジェクトを得ること。
|
220
|
+
|
221
|
+
|
222
|
+
|
223
|
+
1979年から1992年までの間に、call-by-sharing を使わなくなった理由は不明。
|
224
|
+
|
225
|
+
|
226
|
+
|
227
|
+
CLUを調べることで、他の回答者の議論になんとか追いつくことができました。概要だけみるとCLUは、Javaや、pythonの祖先といってよいほど似ている。pythonはCLUの嫡子でしょう。抽象データ型には触れなかったが、ほんとうの研究の成果はここにあると思います。その他、仕事で出会った古いALOGOLコードにCLU由来の考えがあったのを思い出した。
|
228
|
+
|
229
|
+
|
230
|
+
|
231
|
+
### 命名
|
232
|
+
|
233
|
+
英文 wikipedia で call by sharing は共通合意ではないといっているが、1979年の議論は解説する必要があるでしょう。1992年にはオブジェクトのポインターを代入すると言っているので、値渡しの範囲に分類できる。call by object は資料の中に見つけられなかったので採用しません。
|
234
|
+
|
235
|
+
|
236
|
+
|
237
|
+
英語に便利な言い方があります、等値の ', or'(すなわち)を使います。
|
238
|
+
|
239
|
+
|
240
|
+
|
241
|
+
call by sharing, or call by reference value
|
242
|
+
|
243
|
+
共有呼び、すなわち参照の値呼び
|
244
|
+
|
245
|
+
|
246
|
+
|
247
|
+
すごく常識的になりました。内容に誤りがあればご指摘ください。
|
1
CLUを追記
test
CHANGED
@@ -59,3 +59,115 @@
|
|
59
59
|
|
60
60
|
|
61
61
|
wikipediaに記述するなら、評価戦略という観点から、歴史的順序、標準化の程度、依存関係、抽象化の度合いなどを、どう規定するかが著者に求められませんか?もちろん、逆引き用語集のように網羅的、索引的な記述をしてもよいが、作業量は増えます。その作業がかえって観点確立に役立つかもしれないけれど。
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
### CLU (2019-05-02)
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
CLUにプリミティヴ型変数はなく参照型変数しかない。関数呼び出しは仮引数に実引数の参照をコピー代入することで行う。Javaにあわせて表を作ると以下のようになる。
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
|variable type|call by value|call by reference|call by sharing|call by name|
|
74
|
+
|
75
|
+
|:--|:--:|:--:|:--:|:--:|
|
76
|
+
|
77
|
+
|reference type|◯|-|◯|-|
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
以下は言語の設計過程で行われた検討。
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
**オブジェトをヒープ、スタックのどちらに置くか**
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
Simula 67 がCLUの目指す設計に最も近かったが、Simula 67 はオブジェクトをスタック、ヒープの両方に置く方式を採用。CLU はすべてのオブジェクトをヒープに置く。理由は、状態遷移する mutable オブジェクトを採用したため可変長オブジェクトの更新にはヒープが有利だったのと、オブジェクトの生存期間をプロセジャのスコープより長くしたかったから。当然 GC を採用した(懸垂参照(ポインタ)の議論がちょっとある)。
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
**ヒープ、スタック**
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
ヒープとシングルスタックを採用する。並行処理(マルチスタック)を考えたが途中で放棄した。スレッド共有という考えはない。
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
**オブジェト**
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
built-in type 、 user-defined type 、 procedure / iterator の三種類。
|
106
|
+
|
107
|
+
- built-in type Javaにおけるプリミティヴ型 (immutable)、配列などの集合型 (mutable/immutable)。
|
108
|
+
|
109
|
+
- user-defined type ユーザーが定義するクラス(属性と振舞を持つ。カプセル化を実現)。clusterと呼ぶ。(function cluster)
|
110
|
+
|
111
|
+
- procedure / iterator 関数(第一級のオブジェクト)
|
112
|
+
|
113
|
+
cluster (クラス) に継承という考えはない。パラメトリック・ポリモーフィズム(Javaのジェネリックスに相当。型変数を伴いコンパイル時にチェック)を採用。cluster は抽象データ型のアイデアを実装。抽象、つまり公開する振る舞い(Javaのインタフェースに相当)と実装、表現(representation)とを分離、定義する。
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
**オブジェクト共有**
|
118
|
+
|
119
|
+
|
120
|
+
|
121
|
+
スタック上の変数はオブジェクトの実体ではない。オブジェクトの実体はヒープに存在する。変数はオブジェトを参照するのみ。ここから、複数の変数が同じオブジェクトを参照(共有する)という事態が起こる。共有の本質は参照のコピー代入である。共有はどこで起こるのか。
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
- スタック上の複数の変数がヒープ上のオブジェクトを共有する。
|
126
|
+
|
127
|
+
- cluster の private 変数によって、ヒープ上の複数のオブジェクトが別のオブジェクトを共有する。再帰的な共有の連鎖も可能。
|
128
|
+
|
129
|
+
- 関数呼び出しによって、呼び元の実引数と呼び先の仮引数が、ヒープ上のオブジェクトを共有する。
|
130
|
+
|
131
|
+
|
132
|
+
|
133
|
+
代入においてオブジェトの実体コピーとは何かという問いがたてられ、深いコピー/浅いコピーの違いや、真の実体を代入するために、by-reference パラメータを使う代入(Alfard)などが検討された。
|
134
|
+
|
135
|
+
|
136
|
+
|
137
|
+
**call-by-sharing 共有の何が新しいと思ったのか**
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
<ここ、追記予定>
|
142
|
+
|
143
|
+
|
144
|
+
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
|
149
|
+
**call-by-object という用語の否定**
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
リスコフは、call-by-sharingと同じ意味で使っていない。以下は、プロセジャで(参照の共有があっても)変数の共有がないことを説明する箇所。
|
154
|
+
|
155
|
+
|
156
|
+
|
157
|
+
> In fact, CLU procedures do not share variables at all. In addition to there being no free variables, there
|
158
|
+
|
159
|
+
is no call-by-reference. Instead arguments are passed "by object"; the (pointer to the) object resulting
|
160
|
+
|
161
|
+
from evaluating the actual argument expression is assigned to the formal.
|
162
|
+
|
163
|
+
|
164
|
+
|
165
|
+
'A History of CLU' Barbara Liskov, 1992
|
166
|
+
|
167
|
+
|
168
|
+
|
169
|
+
free variables は LISP の用語で(束縛されない)自由変数と訳せるが、ここではグローバル変数のこと。
|
170
|
+
|
171
|
+
"by object" は、call-by-reference のこと。(暗にC++のような深いコピーを渡すことも指していると勝手に解釈)
|
172
|
+
|
173
|
+
object resulting from evaluating the actual argument expression は、正格処理として実引数の式を評価して結果オブジェクトを得ること。変数自体も式である。
|