2008-01-07

Call-by-*

冬休みは今日で最後です。結局数学Bが…orz

まぁ期限はまだまだ先なんで、期限にさえ間に合えば別に評価が変わることはないんですが、

なんか自分に負けた気分だ...orz orz orz



というか、実際は各教科の予習復習も、電子回路/プログラミング言語論の過去問も

手を付けられなかったわけだし…駄目人間過ぎるわ。

さらなる時間圧縮をするしかない。





[前提]
#define NUMLISTSIZE 100
for (index = 0; index i = 5;
j = 6;
k = 3;
func(k, i, numlist[i*j]);


[Call-by-Value]
・実引数をcallerの環境で評価
・その評価結果のコピーを仮引数に代入してcalleeを実行
・仮引数の値が変更されても、対応する実引数には影 響しない
・大域変数など、引数で渡されないcalleeのスコープ外の変数を変更すれば、
callerの環境に影響する

func関数の引数には、各引数の値を呼び、別々の変数として扱う。
一般的な使い方。


[Call-by-Value/Result]
・実引数をcallerの環境で評価
・その評価結果のコピーを仮引数に代入してcalleeを実行
・calleeから復帰時に仮引数の値を実引数に代入
・仮引数の値が変更されると、対応する実引数に影響する
・復帰時におけるコピーは、
RHVの評価にはcalleeの環境を、
LHVの評価にはcallerの環境を用いる
ex.入力時にs[i*j(=3)]のとき
× s[3]=n
○ s[i*j]n
となる。また、×の復帰方法を、Call-by-Copyと呼ぶ。

*問題点
Call-by-Value/ResultはALGOL Wなどで採用されたが、
機構が複雑になるため処理系の実行効率が悪いため、
他の言語で採用されることはほとんどなかった

func関数の引数には、各引数の値を呼び、別々の変数として扱う。
ただし、func関数の動作後、引数から得た局所変数の結果を、引数に返す。

*func関数動作後の式の評価は、その瞬間の変数によって左右されることに注意する。
→cf. numlist[i*j] = Ncopy;


[Call-by-Reference]
・実引数をcallerの環境で評価
・その評価結果の参照(reference)を仮引数に代入してcalleeを実行
・仮引数の値が変更されると、対応する実引数に影響する

引数には変数のメモリ番地を呼び出して使う
→func関数内で引数が書き換えられた場合、そのメモリ番地を書き換えてしまう
→func関数に引数として与えた変数の値が変わる可能性がある。
cf.ポインタ


[Call-by-Name]
・実引数を評価せずに、式のまま仮引数に代入する
・実引数とともに、その実引数を評価するのに十分な、
callerの環境の部分集合も受け渡す
・式とその評価に用いる環境の組を、閉包(closure)と呼ぶ
・calleeの中で仮引数を評価するたびに、仮引数に代 入された実引数を、
閉包に与えられた環境を用いて評価する


printf("N=%d\n", (N));\
// N==numlist[i*j]
例えば、上式の場合、式が呼び出された瞬間のiとjの値が呼び出される。
このとき、i=11, j=6とすれば、numlist[11×6]=66が呼び出される。
つまり、call-by-Name → 呼び出される瞬間の変数を参照する使い方となる。

擬似言語について基本的な構造はcall-by-textに似ているが、
局所変数j_renameを用いるかどうかが違う。
call-by-name → j_renameを使う
call-by-text → jをそのまま使う


[Call-by-Copy]
・実引数の参照を取得
・参照に格納されている値のコピーを仮引数に代入してcalleeを実行
・calleeから復帰時に仮引数の値を取得した実引数の参照の格納領域に代入
・仮引数の値が変更されると、対応する実引数に影響する

funcの関数を行う前に事前に、各引数のメモリ番地をコピーする。
funcの関数内では別々の変数として扱う。
func関数が終わったら、各引数の値を適切なメモリ番地に格納する


[Call-by-Text]
・実引数を評価せずに、式のまま仮引数に代入する
・仮引数に代入された式(実引数)は、calleeの環境で
定義されている変数はcalleeの環境を用いて、
それ以外はcallerの環境を用いて評価する
・意味としては、以下のマクロ展開をすることと同じ
・callee中で仮引数が出現する箇所を実引数で置き換える

プリプロセッサで擬似関数として動かした関数。
実際にはfunc関数の引数は存在しない。
つまり、main関数でi,j,kに関する各式を書いているに過ぎない。


evaluate=評価する

*thunkについて
1.《コ》サンク◆16ビットのメモリアドレスを32ビットに変換すること。
またはその逆。転じて別アーキテクチャのコードを読み出すこと。
16ビットと32ビットのプログラムではメモリアドレスの振り方が異なるので、
アドレスの変換をして呼び出す必要がある。

2.メモリアドレス(ポインタ)を返す(引数を持たない)関数 T *thunk()
なぜ “thunk” という名称なのかは諸説ある
ある式が実引数として関数に与えられるとき、
その式 の参照(つまりLHV)が必要な場合、その式を使った
thunkを定義しておき、それを呼び出すことで、その 式の参照が取得できる
int *n_thunk() { return &(s[i*j]); }
thunkを定義し、その関数へのポインタを受け渡すことができれば、
閉包に関係する情報をcalleeに与えることができる


[方針]
1、reference, name, value/referenceを順に適用
2、値が正しいか確認する。
3、適宜必要ならば修正する。

[refer to the lecture of PLT ]

3 件のコメント:

比丘 さんのコメント...
このコメントは投稿者によって削除されました。
匿名 さんのコメント...

やってますな。

時間の使い方は重要っすね。僕は明らかに残しとくと死にそうな英語のレポートだけ休み中に片付けますた。テストまでシコ勉します。シコシコ。

yasulab さんのコメント...

2重投稿乙w

勉強終わったら今度こそ飲みに行くぞ。