IS CS-2024S-04

题目来源Problem 4 日期:2024-08-17 题目主题:CS-Programming Languages-Call-by-Value vs. Call-by-Name

解题思路

在这道题中,我们主要研究了函数 在不同调用策略下的行为。为了回答所有问题,我们首先需要理解如何在 C 语言风格的伪代码中用“值调用”(call-by-value)来执行 函数。然后,我们将这些分析扩展到“名调用”(call-by-name)的情况下,并最终寻找在不同调用策略下表现不同的程序示例。

Solution

1. Number of Calls of the Function During the Evaluation of

First, let’s evaluate step by step:

To summarize:

  • calls ,
  • directly returns ,
  • is equivalent to which involves 3 calls as shown in the question statement.

Thus, the total number of calls during the evaluation of is 5.

2. Showing that the Return Value of is 1 for Every Non-Negative Integer

Let’s prove this statement by induction on .

Base Case: For , we have:

So, .

Inductive Step: Assume that for all where is some positive integer. Consider :

By the inductive hypothesis, (since ). Hence,

Therefore, by induction, for all non-negative integers .

3. Number of Calls of the Function During the Evaluation of in Terms of

To determine the number of calls during , observe the recursive pattern:

Let represent the number of calls for . We have:

Starting with the base cases:

So for even :

Thus,

For odd :

So we can express it as:

4. Number of Calls of the Function with Call-by-Name Strategy in Terms of

When using call-by-name, the function argument is not evaluated at the moment of the function call, but instead, every occurrence of the argument in the function body is replaced by the original expression.

For the function , this results in exponential growth in calls because each nested call of introduces additional nested calls. Specifically:

Each introduces an entirely new evaluation of . This results in a number of function calls that grows exponentially with . This is much larger than the linear or polynomial number of calls observed with the call-by-value strategy.

5. Example of a Program that Does Not Terminate with Call-by-Value but Terminates with Call-by-Name

Consider the following function:

int g(int x, int y)
{
    if (x <= 0) return 1;
    else return g(x - 1, y) + g(x - 1, y);
}

If we call this with:

g(2, some_function())

Here, if some_function() has an infinite loop, the program will not terminate under call-by-value, because some_function() will be evaluated before entering g. However, under call-by-name, some_function() will only be evaluated when y is actually used in the function body, which may never occur if x <= 0 condition is met first, leading to termination.

知识点

递归函数编程语言调用策略值调用名调用

难点思路

在解决这道题目时,主要的难点在于理解不同调用策略如何影响递归函数的计算次数和返回值。尤其是对于 call-by-name 策略,理解参数传递的延迟计算(lazy evaluation)如何导致不同的函数行为。

解题技巧和信息

  • 对于递归函数,可以利用归纳法证明递归终止条件和返回值的一致性。
  • 需要熟悉 call-by-value 和 call-by-name 两种调用策略的差异,尤其是它们如何影响函数调用的次数和执行顺序。

重点词汇

  • Call-by-Value: 值调用
  • Call-by-Name: 名调用
  • Recursion: 递归
  • Evaluation Strategy: 计算策略

参考资料

  1. Programming Languages: Concepts and Constructs (Chapter on Evaluation Strategies)
  2. Types and Programming Languages, Benjamin C. Pierce (Chapter on Operational Semantics)