2012/2/2

call-by-name 源自於 Algol60,很像C的巨集macro。

其實 call-by-name 並不等於 call-by-reference。call-by-name 源自於 Algol60 這

古早的程式語言,它定義了兩種參數傳遞方式,call-by-value 與 call-by-name,其

call-by-name 被定義為 Name Replacement:「參數列中的每個參數,如果未指定以
傳值的方式來傳遞,就必須以實際傳入的參數來取代。」在 Compilers - Principles,

Techniques, and Tools 這本書的 7.5 節中,它被解釋為 inline-expansion。其原因
是,以 call-by-name 的方式呼叫函式時,如果在某個參數位置上指定了一個運算式
(expression) 當作參數,那麼這個 expression 會被直接傳入函式裡面進行展開,所
以,
這個 expression 是在函式裡面才進行運算的,而不是在參數列中預先計算好它的值再

進去。這就產生了 delayed evaluation (延遲計算) 的效果。delayed evaluation 的
好處
是,只有當函式需要某個 expression 參數的值,該 expression 才會被計算,否則就

用了。call-by-name 比較顯著的例子是 swap 函式,swap 通常是這樣寫的:

proc swap(A, B) {
tmp = A;
A = B;
B = tmp;
}

proc main() {
i = 2;
a[3] = {5, 6, 7};
swap(i, a[i]);
}

swap 的實際工作情形是:

swap(i, a[i]) { // i is 2
tmp = i; // tmp becomes 2, since i is 2
i = a[i]; // i becomes 7, since a[2] is 7
a[i] = i; // inline expansion of B, delayed evaluation ==> a[7] = 7
}

在 P(X, Y, Z) 這個例子中:

proc P(X, Y, Z) {
Y = Y + 1;
Z = Z + X;
}

P(a+b, a, a) { // a = 2, b = 3
a = a + 1; // a becomes 3
a = a + (a+b); // inline expansion of X, a becomes 9
}

沒有留言:

張貼留言