gpt4 book ai didi

evaluation - 按名称调用与通过宏扩展调用

转载 作者:行者123 更新时间:2023-12-02 20:19:48 29 4
gpt4 key购买 nike

在非严格求值语言中,使用按名称调用通过宏扩展调用有何区别和优点/缺点?

您能否提供一个示例来解释这两种评估策略?

谢谢!

最佳答案

按姓名调用:

按名称调用是一种求值策略,其中函数的参数在调用函数之前不会求值,而是直接替换到函数体中(使用避免捕获替换),然后在它们出现时进行求值出现在函数中。如果函数体中未使用参数,则永远不会计算该参数;如果多次使用,则每次出现时都会重新评估。 (参见 Jensen 的设备。)

按名称调用评估有时比按值调用评估更可取。如果函数中未使用函数的参数,则按名称调用将不计算参数,从而节省时间,而按值调用则无论如何都会计算它。如果参数是非终止计算,则优势是巨大的。然而,当使用函数参数时,通过名称调用通常会比较慢,需要诸如 thunk 之类的机制。

早期使用的是 ALGOL 60。当今的 .NET 语言可以使用委托(delegate)或表达式参数模拟按名称调用。后者导致为该函数提供一个抽象语法树。 Eiffel 提供代理,代表需要时评估的操作。 Seed7 提供带函数参数的名称调用。

通过宏调用:

通过宏扩展调用与通过名称调用类似,但使用文本替换而不是避免捕获替换。如果使用不谨慎,宏替换可能会导致变量捕获并导致不良行为。卫生宏通过检查和替换不是参数的隐藏变量来避免这个问题。

注意:在非严格评估语言中

宏调用示例:

Call by Macro Expansion: many programming languages, including C, lisp and scheme, provide developers with a mechanism to add new syntax to the core language grammar called macros. Macros are expanded into code by a macro preprocessor. These macros might contain arguments, which are copied in the final code that the preprocessor produces. As an example, the C program below implements the swap function via a macro:

#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); }

该宏实现了一个有效的交换例程。

preprocessed program will look like the code below. Because the body of the macro is directly copied into the text of the calling program, it operates on the context of that program. In other words, the macro will refer directly to the variable names that it receives, and not to their values.

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); }

The expressions passed to the macro as parameters are evaluated every time they are used in the body of the macro. If the argument is never used, then it is simply not evaluated. As an example, the program below will increment the variable b twice:

#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); } Macros suffer from one problem, called variable capture. If a macro defines a variable v that is already defined in the environment of the caller, and v is passed to the macro as a parameter, the body of the macro will not be able to distinguish one occurrence of v from the other. For instance, the program below has a macro that defines a variable temp. The call inside main causes the variable temp defined inside this function to be captured by the definition inside the macro's body.

#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); }

一旦该程序扩展

the C preprocessor, we get the code below. This program fails to exchange the values of variables temp and a:

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); }

有多种惰性评估策略

that avoid the variable capture problem. The two best known techniques are call-by-name and call-by-need.

按姓名调用示例:

Call by Name: in this evaluation strategy the actual parameter is only evaluated if used inside the function; however, this evaluation uses the context of the caller routine. For instance, in the example below, taken from Weber's book, we have a function g that returns the integer 6. Inside the function f, the first assignment, e.g., b = 5, stores 5 in variable i. The second assignment, b = a, reads the value of i, currently 5, and adds 1 to it. This value is then stored at 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;
}

Very few languages implement the call by name evaluation strategy. The most eminent among these languages is Algol. Simula, a direct descendent of Algol, also implements call by name, as we can see in this example. The call by name always causes the evaluation of the parameter, even if this parameter is used multiple times. This behavior might be wasteful in referentially transparent languages, because, in these languages variables are immutable.

关于evaluation - 按名称调用与通过宏扩展调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44490619/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com