2017-06-12 124 views

回答

2

調用由名稱:

通過名字來稱呼是在參數的函數不被評估爲被叫,而函數之前,它們直接代入函數體的評估策略(使用捕獲 - 避免替換),然後在函數中出現時進行評估。如果在函數體中沒有使用參數,則參數永遠不會被計算;如果多次使用,每次出現時都會重新評估。 (請參閱Jensen的設備。)

名稱評估有時候更適用於按價值評估。如果在函數中沒有使用函數的參數,那麼通過名稱調用將通過不評估參數來節省時間,而按值調用將會評估它。如果參數是非終止計算,優點是巨大的。但是,當使用函數參數時,按名稱調用通常比較慢,需要使用thunk等機制。

早期使用的是ALGOL 60.今天的.NET語言可以使用委託或表達式參數按名稱模擬調用。後者導致爲函數提供一個抽象語法樹。艾菲爾提供代理,代表需要時評估的操作。 Seed7通過名稱和功能參數提供呼叫。

調用由宏:

通過電話宏展開類似的名字來稱呼,但使用文本替換,而不是捕捉避免替代。在不謹慎使用的情況下,宏觀替代可能導致變量捕獲並導致不希望的行爲。衛生宏通過檢查並替換不是參數的陰影變量來避免此問題。

注:在非嚴格的評價語言

實例調用由宏:

呼叫由宏擴展:許多編程語言,包括C,口齒不清 和方案,爲開發者提供一種將新語法添加到名爲宏的核心語言語法 的機制。宏由宏預處理器擴展爲代碼 。這些宏可能包含參數,其中 被複制到預處理器生成的最終代碼中。作爲一個 例如,C程序下面經由宏實現交換功能:

#define SWAP(X,Y) {int temp=X; X=Y; Y=temp;} int main() { int a = 2; int b = 3; printf("%d, %d\n", a, b); SWAP(a, b); printf("%d, 
> %d\n", a, b); } 

該宏實現有效的交換例程。

預處理程序看起來像下面的代碼。因爲宏的主體 直接複製到調用程序的文本中,所以它在該程序的上下文中操作。換句話說,宏 將直接引用它接收的變量名稱,而不是 它們的值。

int main() { int a = 2; int b = 3; printf("%d, %d\n", a, b); { 
> int tmp = (a); (a) = (b); (b) = tmp; }; printf("%d, %d\n", a, b); } 

傳遞給宏表達式作爲參數進行評估它們在宏觀的主體中使用的每個 時間。如果參數從不使用 ,那麼它就不會被評估。例如,下面的程序 會使變量b增加兩次:

#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) int main() { int a = 2, b = 3; int c = MAX(a, b++); printf("a = %d, b = %d, c = %d\n", a, b, c); }宏受到一個問題的困擾,稱爲變量捕獲。如果一個 宏定義了一個變量v,該變量v已經在調用方的環境 中定義,並且v作爲參數傳遞給宏,宏的主體 將無法​​區分v的一次出現與 其他。例如,下面的程序有一個宏,它定義了一個 變量temp。主函數內部的調用導致該函數內部定義的變量temp被定義爲 宏內部的定義。

#define SWAP(X,Y) {int temp=X; X=Y; Y=temp;} int main() { int a = 2; int temp = 17; printf("%d, temp = %d\n", a, temp); SWAP(a, temp); 
> printf("%d, temp = %d\n", a, temp); } 

一旦這個程序是由

C預處理程序擴展,我們可以得到下面的代碼。此程序無法 交換變量溫度和值:

int main() { int a = 2; int temp = 17; printf("%d, temp = %d\n", 
> a, temp); {int temp=a; a=temp; temp=temp;}; printf("%d, temp = 
> %d\n", a, temp); } 

有一些懶惰的評估策略

是避免變量捕捉問題。兩種最着名的技術 分別是按名稱和按需呼叫。

示例呼叫用名字:

打電話名稱:在該評價中的策略,如果在函數內部中使用的實際參數僅 評價;但是,此評估使用調用程序例程的上​​下文 。例如,在下面的例子中, 取自韋伯的書,我們有一個函數g,返回整數 6.在函數f中,第一個賦值,例如b = 5,將5存儲在變量i中。第二個作業b = a讀取當前爲5的i, 的值,並將其加1。這個值然後存儲在i處。

void f(by-name int a, by-name int b) { 
    b=5; 
    b=a; 
} 
int g() { 
    int i = 3; 
    f(i+1,i); 
    return i; 
} 

很少有語言實現通過名稱評估策略調用。在這些語言中最着名的 是Algol。 Simula,Algol的後代直接 ,也實現了通過名稱的呼叫,我們可以在 這個例子中看到。即使此參數多次使用,通過名稱的呼叫始終會導致對參數 的評估。這種 行爲在引用透明的語言012ff中可能會浪費,因爲在這些語言中變量是不可變的。

+0

感謝@sugansoft,但這看起來像https://en.wikibooks.org/wiki/Introduction_to_Programming_Languages/Evaluation_Strategies中的複製粘貼。您的答案中並未詳細說明兩種評估策略之間的差異和優勢/劣勢。 –