回答
調用由名稱:
通過名字來稱呼是在參數的函數不被評估爲被叫,而函數之前,它們直接代入函數體的評估策略(使用捕獲 - 避免替換),然後在函數中出現時進行評估。如果在函數體中沒有使用參數,則參數永遠不會被計算;如果多次使用,每次出現時都會重新評估。 (請參閱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中可能會浪費,因爲在這些語言中變量是不可變的。
- 1. 通過名稱自動呼叫值
- 2. 呼叫通過「串」
- 3. 呼叫通過接口
- 4. 呼叫通過反射
- 5. JSP呼叫通過HREF
- 6. 呼叫通過反射
- 7. 通過AJAX呼叫PHP
- 8. 斯卡拉流按需呼叫(懶惰)vs按名稱呼叫
- 9. 星號呼叫文件呼叫未通過
- 10. Android呼叫狀態通過「呼叫」類(API 23)
- 11. 查看呼叫器結束後通過意向呼叫活動
- 12. Twilio網絡掛接(的NodeJS) - 在呼入呼叫,通過呼叫的SID
- 13. 呼叫在Magento的擴展
- 14. 呼叫wPaint擴展功能
- 15. 通過名稱而不是ID來呼叫Wordpress類別
- 16. 通過名稱與正常順序的呼叫
- 17. 呼叫時通過按引用
- 18. 通過引用與QVector呼叫
- 19. Android的修改呼叫通過AOSP
- 20. 的fancybox - 如何通過人工呼叫
- 21. 通過https的Ajax呼叫SSL
- 22. 無法通過活動呼叫服務
- 23. 通過跨域JavaScript呼叫預防CSRF
- 24. 通過DMZ進行代理呼叫
- 25. VoIP呼叫如何通過防火牆
- 26. 呼叫控制器動作通過JavaScript
- 27. 通過https訪問PHP Soap呼叫
- 28. 通過意向發起SIP呼叫
- 29. URL呼叫通過文本字符串
- 30. 通過鼠標點擊呼叫功能
感謝@sugansoft,但這看起來像https://en.wikibooks.org/wiki/Introduction_to_Programming_Languages/Evaluation_Strategies中的複製粘貼。您的答案中並未詳細說明兩種評估策略之間的差異和優勢/劣勢。 –