Call By Name

说明网址: http://libai.math.ncu.edu.tw/bcc16/C/C/b14.shtml
-------------------------------------------------------------------------------
其實 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

}
----------------------------------------------------------
您提供的參考網址中有一句話, 或許可以拿來這邊做解釋
「在計算機裡面,一個變數的位址,才是它真正的名字。」
也就是說, call-by-name 的意義等同於call-by-address
只是 call-by-address 是直接給了人類無法直接理解的位址
call-by-name 則是給了人類可以直接理解的代號(ex:test[]的 "test")
大概是這樣子吧?@@a...
我是看了您給的參考網址得出這樣的結論, 現學現賣:p
----------------------------------------------------------

链接:http://jpkc.nwpu.edu.cn/jp2005/20/kcwz/zdnd/z5.html

7.过程说明和过程调用

过程说明的翻译主要完成如下工作:

(1)填写符号表将过程的相关信息填写到表中,由于过程名不同于其他变量名,往往需使用“过程信息向量”记录其入口地址、各参数信息;

(2)产生将调用点地址压入栈的代码;

(3)产生形、实参结合的代码;

(4)产生过程体的翻译代码;

(5)产生返回调用点的代码。

实现过程说明和调用还应解决实参与形参间的信息传递(简称形实结合)的方式问题。常见的形实结合方式有引用调用、值调用、结果调用、值结果调用以及名字调用等等:

引用调用(Call by reference)这种方式是在过程调用的代码序列中给出实参的地址(如果实参是简单变量或下标变量,则在调用代码序列中直接给出其地址;显然,按此种方式实现形实结合,执行过程时,对形参的赋值将会影响相应实参之值(右值)。

值调用(Call by value)值调用也是一种经常采用的方式(PASCAL语言中的值参、C语言中的所有参数等等)。结合方式是,送入形式单元的不是相应实参的地址而是它的值。在执行过程体期间,除了以实参之(右)值作为形参的初值进行运算之外,将不再与实参发生任何联系。

结果调用(Call by result)和值结果调用(Call by value-result)其特点是,为每个形参分配两个形式单元,第一单元用于存放实参的地址(左值),第二单元用于存放实参的(右)值(在结果调用中,实参的值将不被传送),在执行过程体时,将只对第二单元进行操作,但在返回时,将第二单元的内容,按相应的第一单元中的地址传给实参。

名字调用(换名调用Call by name)在早期的ALGOL语言中使用,其原理是,将形参视为过程体中的一个宏,形实结合时,将形参在过程体的每个出现,均用实参表达式取而代之,为避免引起运算顺序变化,结合时将自动为实参表达式加上括号。

对于过程调用语句的翻译,要点是:

(1)翻译计算各实参表达式的代码,并将此代码段入口放入队列;

(2)将计算实参表达式的入口队列翻译为入口参数四元式

(par,0,0,Ai)

(3)生成转向过程子程序的四元式(call ,0,0,P)

------------------------------------------------------------------------------------------------------------------
东南大学编译原理网络课堂52讲里对call by name的解释

传名过程调用相当于把被调用段的过程代替调用语句,并且过程体内形参名皆用相应的实参名代替


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值